Kodun bulunduğu derleme yolunu nasıl edinebilirim?


781

Geçerli kodun bulunduğu montajın yolunu almanın bir yolu var mı? Çağıran derleme yolunu istemiyorum, sadece kodu içeren bir yol.

Temelde benim birim test dll göre bulunan bazı xml test dosyalarını okumak gerekiyor. Test dll TestDriven.NET, MbUnit GUI ya da başka bir şey çalıştırılırsa olsun her zaman doğru bir şekilde çözümlemek istiyorum.

Edit : İnsanlar ne soruyorum yanlış anlıyor gibi görünüyor.

Test kütüphanem:

C: \ projeler \ myapplication \ daotests \ Bin \ Debug \ daotests.dll

ve ben bu yolu almak istiyorum:

C: \ projeler \ myapplication \ daotests \ bin \ Debug \

MbUnit Gui'den çalıştırdığımda şu ana kadar üç öneri başarısız oldu:

  • Environment.CurrentDirectory verir \ Program Files \ MbUnit: c

  • System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location verir \ Documents and Settings \ George \ Local Settings \ Temp \ .... \ DaoTests.dll: C

  • System.Reflection.Assembly.GetExecutingAssembly().Location öncekiyle aynıdır.


102
Bu sizin çözümünüz: var dir = AppDomain.CurrentDomain.BaseDirectory;
Jalal El-Shaer

7
Bu kabul edilen çözüm olmalıdır. AppDomain.CurrentDomain.BaseDirectory doğru yaklaşımdır.
aBetterGamer


2
Buraya pacakge dizininden bir JSON dosyasını okumak için bir nuget paketi için bir çözüm aramaya geldim. Bir nuget paketi yürütüldüğünde "AppDomain.CurrentDomain.BaseDirectory" nuget paket dizinini değil, çalışan projeler dizinini gösterir. Bunların hiçbiri nuget paket dizinini doğru bir şekilde hedeflemiyor gibi görünüyor.
Lucas

@Lucas hayır olmazdı çünkü bu soru bununla ilgili değildi (aslında sorulduğunda, nuget yoktu) - yeni bir soru başlatmaktan ve bana ping atmaktan çekinmeyin, ancak şimdi size söyleyebilirim çoğu durumda imkansız. Çoğu proje için nuget dizini packagessln dosyasının yanındadır. AMA bir şeyler derlemek ve dağıtmak zaman hiçbir sln dosyası ve paketleri dizini yoktur. Derleme sırasında, gerekli olan şeyler (ancak her şey değil) bin dizinine kopyalanır. En iyi seçeneğiniz, istediğiniz dosyayı kopyalamak için bir postbuild betiği kullanmaktır.
George Mauer

Yanıtlar:


1036

Bu özelliği birim testlerinde sık kullandığımız için aşağıdaki özelliği tanımladım.

public static string AssemblyDirectory
{
    get
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        string path = Uri.UnescapeDataString(uri.Path);
        return Path.GetDirectoryName(path);
    }
}

Assembly.Location(Montajlar geçici klasörden çalıştırın) NUnit kullanırken özellik bazen kullanım tercih böylece, bazı komik sonuçlar verir CodeBasesize URI biçiminde yolunu verir, daha sonra UriBuild.UnescapeDataStringkaldırır File://başında ve GetDirectoryNamenormal bir pencere biçimine değiştirir .


29
Dizin adınız c: \ My% 20Directory ise Uri.UnescapeDataString döndürecektir: c: \ My Directory Bu File.Exists ("c: \ My Directory \ MyFile.txt ") doğru yol olduğu için yanlış döndürür" c: \ My% 20Directory \ MyFile.txt "SVN yollarımızda boşluklar olduğu ve bunları kontrol ettiğimizde boşlukları kodladığı için bununla karşılaştım.
row1

5
Bu yöntemi UNC yolunda false döndüreceğinden, File.Exist () öğesini denetlemek için kullanırken dikkatli olun. Onun yerine @ Keith'in cevabını kullan.
AZ.

3
Genelden önce statik koyabileceğinizi bilmiyordum. Bilmek güzel ve okunabilirliği tercih
ettiğimi

5
Not: Bu ağ konumlarıyla çalışmaz (örn. \\ REMOT_EPC \ Klasör)
Muxa

5
Dizinde '#' numara işareti varsa da bu çalışmaz. Windows'daki dizin ve dosya adlarında sayı işaretlerine izin verilir.
Huemac

321

Bu yardımcı olur mu?

//get the full location of the assembly with DaoTests in it
string fullPath = System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location;

//get the folder that's in
string theDirectory = Path.GetDirectoryName( fullPath );

benim düzenlememe bakın, değil, MbUnit'in işleri nasıl yaptığı hakkında garip bir şey mi?
George Mauer

3
Xml dosyalarını dll'den okunan içerik, dll veya kaynaklarla kopyalanacak şekilde ayarlayın.
Keith

22
Veya sadecetypeof(DaoTests).Assembly
SLaks

4
@SLaks @JohnySkovdal @Keith: Hey millet, kullan Assembly.GetExecutingAssembly(). Bu "yürütülmekte kodunu içeren montaj alır" (yöntem açıklamadan). Bunu " EntitiesToDTOs " eklentimde kullanıyorum . Gerçek örnek için AssemblyHelper.cs dosyasına bakın .
kzfabi

4
UNC yolları için çalışıyor gibi görünmüyor gibi @John Silby tarafından yazı ile ilgili bir sorun vardı ... eg \\ Server \ Folder \ File.ext. Bu hile yaptı. +1
Yabanmersini

312

Bu kadar basit:

var dir = AppDomain.CurrentDomain.BaseDirectory;

11
Bu kabul edilen çözüm olmalıdır. AppDomain.CurrentDomain.BaseDirectory doğru yaklaşımdır.
aBetterGamer

5
dikkatimi buna geri getirdiğin için teşekkür ederim - soruyu sorduğum anda mevcut olup olmadığından emin değilim ama şimdi.
George Mauer

120
Hayır, bu yanlış. Bu, yürütülmekte olan kodun değil ORİJİNAL GİRİŞ NOKTASININ yolunu döndürür. Bir montajı farklı bir yoldan manuel olarak yüklediyseniz veya GAC'den yüklenmişse yanlış sonuç döndürür. Bu cevap doğrudur: stackoverflow.com/a/283917/243557 Daha hızlı Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location).
nathanchere

9
Aslında bu web uygulamalarında işe yaramaz ama buldum kadarıyla aşağıdaki büyütme her türlü uygulama için çalışması gerekir:AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory
Ilya Chernomordik

4
Test düzeneğinizin orijinal kutu yolunu almak istiyorsanız (örneğin, alt klasörlerde yardımcı veri dosyalarına ulaşmak için) birim testi için mükemmeldir. Test düzeneği, kodunuzun giriş noktasıdır.
MarioDS

68

John'un cevabı ile aynı, ancak biraz daha az ayrıntılı bir genişletme yöntemi.

public static string GetDirectoryPath(this Assembly assembly)
{
    string filePath = new Uri(assembly.CodeBase).LocalPath;
    return Path.GetDirectoryName(filePath);            
}

Şimdi şunları yapabilirsiniz:

var localDir = Assembly.GetExecutingAssembly().GetDirectoryPath();

veya isterseniz:

var localDir = typeof(DaoTests).Assembly.GetDirectoryPath();

6
Ne demek mi assemblyyerine Assembly.GetExecutingAssembly()?
Dostum Pascalou

3
Dude'un işaret ettiği gibi, bir argümandan geçtiniz ve onu kullanmadınız.
Chris Moschini

4
Bu cevap eldeki soru için basit bir yanlıştır. Bu cevabın değiştirilmiş bir versiyonu size verilen bir montajın yolunu verebilir. Bununla birlikte, burada, özellikle yürütme montajını arıyoruz ve bu yüzden bir montajı geçmek mantıklı değil. Bir uzantı yöntemi, iş için yanlış araçtır.
Edward Brey

46

CodeBase ve UNC Network paylaşımlarını kullanırken benim için çalışan tek çözüm:

System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);

Ayrıca normal URI'larla da çalışır.


5
Bu kabul edilen cevap olmalı. Varsayılan kod tabanının UNC paylaşımlarını doğru işlememesi gerçekten can sıkıcı bir durum.
Daniel Gilbert

Klasör boşluklar içerdiğinde ve tanrı diğer karakterleri bildiğinde
çöküyor

1
Bunu çok kullanıyorum ve başarısız olduğu bir senaryo bulduk : bu kod satırı kendisi bir uygulama tarafından kullanılan bir NuGet paketinin parçası ise! Biz değiştirerek de o senaryoyu destekleyebilir GetExecutingAssembly()tarafından GetCallingAssembly().
Timo

@Timo: Bu değişikliğin yan etkileri olup olmadığını doğruladınız mı? Öyleyse lütfen düzeltmeyi eklemek için cevabı düzenleyin.
Ignacio Soler Garcia

@IgnacioSolerGarcia Ne yazık ki sadece bir kat derinlikte çalıştığını rapor etmeliyim, yani NuGet paketi başka bir NuGet paketi tarafından çağrıldıysa başarısız oluyor! Şimdi (Chernomordik bu sayfasında yorum itibaren) bu kullanıyorum: AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory. İlk bölüm web uygulamaları, ikinci bölüm diğer uygulamalar içindir.
Timo

32

Derleme gölge kopyalanmadıkça , bu çalışmalıdır :

string path = System.Reflection.Assembly.GetExecutingAssembly().Location

14

Peki buna ne dersin:

System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

11

Buradaki asıl sorunun test çalıştırıcınızın montajınızı farklı bir yere kopyalaması olduğundan şüpheleniyorum. Çalışma zamanında derlemenin nereden kopyalandığını anlamanın bir yolu yoktur, ancak muhtemelen test çalıştırıcısına derlemeyi bulunduğu yerden çalıştırmasını ve bir gölge dizine kopyalamamasını söylemek için bir anahtar çevirebilirsiniz.

Böyle bir anahtarın elbette her test koşucusu için farklı olması muhtemeldir.

XML verilerinizi test düzeneğinize kaynaklar olarak gömmeyi düşündünüz mü?


Gölge kopyalamayla ilgili sorunu belirtmek için +1. Ancak, aslının bulunduğu yeri belirlemek gerçekten mümkündür Assembly.CodeBase.
tm1

11
AppDomain.CurrentDomain.BaseDirectory

MbUnit GUI ile çalışır.


Bu, bir asp.net web uygulamasında kök dizine göre bir dosya yazmak için harika çalıştı
Philip Pittle

Bunun genel olarak en iyi sonucu verdiğini gördüm. Emin değilseniz seçin.
Erik Bergstedt

10

Bunun her türlü uygulama için işe yarayacağına inanıyorum:

AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory

1
Deneylerim, bunun sadece web ve konsol uygulamalarını değil, aynı zamanda birim testleri ve NuGet paketlerinden (herhangi bir özyineleme seviyesine iç içe) yapılan çağrıları da kapsayan en kusursuz yanıt olduğunu gösteriyor.
Timo

8

Anlayabildiğim kadarıyla, diğer cevapların çoğunda birkaç sorun var.

Disk tabanlı (web tabanlı aksine) GAC olmayan derleme için bunu yapmanın doğru yolu , şu anda yürütülen derlemenin CodeBaseözelliğini kullanmaktır.

Bu bir URL ( file://) döndürür . Dize manipülasyonu ile uğraşmak yerine, veya UnescapeDataStringbu LocalPathözelliği kullanarak en az yaygara ile dönüştürülebilir Uri.

var codeBaseUrl = Assembly.GetExecutingAssembly().CodeBase;
var filePathToCodeBase = new Uri(codeBaseUrl).LocalPath;
var directoryPath = Path.GetDirectoryName(filePathToCodeBase);

1
Yol içeriyorsa çalışmaz #( EscapedCodeBaseçalışır, ancak yol örneğin %20aynen içeriyorsa (Windows yolunda izin verilen bir karakter dizisidir) EscapedCodeBase çalışmaz
Martin Ba

Biz Nuget paketinde bu kodu olmasını istiyorsanız, biz değiştirerek bu senaryoyu çözebilirsiniz GetExecutingAssembly()tarafından GetCallingAssembly().
Timo

8

Buna ne dersin ...

string ThisdllDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

O zaman ihtiyacınız olmayanı kesin


7
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyPath = assembly.GetFiles()[0].Name;
var assemblyDir = System.IO.Path.GetDirectoryName(assemblyPath);

7

İşte John Sibly kodunun bir VB.NET portu. Visual Basic büyük / küçük harfe duyarlı değildir, bu nedenle değişken adlarından birkaçı tür adlarıyla çarpışıyordu.

Public Shared ReadOnly Property AssemblyDirectory() As String
    Get
        Dim codeBase As String = Assembly.GetExecutingAssembly().CodeBase
        Dim uriBuilder As New UriBuilder(codeBase)
        Dim assemblyPath As String = Uri.UnescapeDataString(uriBuilder.Path)
        Return Path.GetDirectoryName(assemblyPath)
    End Get
End Property

6

Bunca yıl boyunca, hiç kimse bundan bahsetmedi. Müthiş ApprovalTests projesinden öğrendiğim bir numara . İşin püf noktası, orijinal dizini bulmak için derlemedeki hata ayıklama bilgilerini kullanmanızdır.

Bu, ÇIKIŞ modunda, optimizasyonların etkinleştirilmesinde veya üzerinde derlenenden farklı bir makinede çalışmaz.

Ancak bu, onu çağırdığınız kaynak kod dosyasının konumuna göre olan yollar elde etmenizi sağlar

public static class PathUtilities
{
    public static string GetAdjacentFile(string relativePath)
    {
        return GetDirectoryForCaller(1) + relativePath;
    }
    public static string GetDirectoryForCaller()
    {
        return GetDirectoryForCaller(1);
    }


    public static string GetDirectoryForCaller(int callerStackDepth)
    {
        var stackFrame = new StackTrace(true).GetFrame(callerStackDepth + 1);
        return GetDirectoryForStackFrame(stackFrame);
    }

    public static string GetDirectoryForStackFrame(StackFrame stackFrame)
    {
        return new FileInfo(stackFrame.GetFileName()).Directory.FullName + Path.DirectorySeparatorChar;
    }
}

5

Bulunduğunuz geçerli dizin.

Environment.CurrentDirectory;  // This is the current directory of your application

.Xml dosyasını derlemeyle kopyalarsanız bulmalısınız.

veya

System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(SomeObject));

// The location of the Assembly
assembly.Location;

montaj gölge kopyalanmışsa bu sorunlu olacaktır .
müsrif

1520! Environment.CurrentDirectoryyürütme derleme GAC içinde bulunduğu ve kodunuzu başka bir yerde olduğu MSBuild görev sınıfında yansıma kullanıyorsanız çalışır.
vulcan kuzgun

4
Genelde CurrentDirectory, yürütülebilir dosyalarınızın nerede olduğunu söylemez. Bunun için kullanılmaz. Sıklıkla çalıştırılabilirlerin bulunduğu konum olduğu için, birçok programcı farkı anlamıyor. Daha sonra, uygulamanın CurrentDirectory'nin uygun kullanımını anlamasını bekleyen bazı son kullanıcılar için sorun yaratırlar.
Bent Tranberg

5

Konum yerine Assembly.CodeBase kullanıyorum:

Assembly a;
a = Assembly.GetAssembly(typeof(DaoTests));
string s = a.CodeBase.ToUpper(); // file:///c:/path/name.dll
Assert.AreEqual(true, s.StartsWith("FILE://"), "CodeBase is " + s);
s = s.Substring(7, s.LastIndexOf('/') - 7); // 7 = "file://"
while (s.StartsWith("/")) {
    s = s.Substring(1, s.Length - 1);
}
s = s.Replace("/", "\\");

Çalışıyor, ancak artık% 100 doğru olduğundan emin değilim. Http://blogs.msdn.com/suzcook/archive/2003/06/26/assembly-codebase-vs-assembly-location.aspx adresindeki sayfa şöyle diyor:

"CodeBase, dosyanın bulunduğu yerin URL'sidir, Konum ise aslında yüklendiği yoldur. Örneğin, derleme internetten indirildiyse, CodeBase" http: // "ile başlayabilir , ancak konumu "C: \" ile başlayabilir. Dosya gölge kopyalanmışsa, Konum gölge kopya dizinindeki dosyanın kopyasının yolu olacaktır. CodeBase'in garanti edilmediğini bilmek de iyidir Ancak konum her zaman diskten yüklenen montajlar için ayarlanacaktır. "

Sen olabilir CodeBase yerine Konumunu kullanmak istiyorum.


1
@Kiquenet: Bir URI'yi yola dönüştürmek için çok fazla kod. Elbette geliştirilebilir. Mike Schall veya SoMoS'un cevabına bakın. URI'leri dize düzeyinde dönüştürmeye çalışmamalı, bunun yerine uygun nesneleri kullanmalısınız. Tamam, Assembly.CodeBase'in URI veya FileInfo gibi daha uygun bir nesne yerine bir dize döndürmesi de beceriksizdir.
Yedi

2

Bin yolunu AppDomain.CurrentDomain.RelativeSearchPath ile alabilirsiniz.


2

Önerilen yanıtların tümü, geliştirici gerekli snippet'i içerecek şekilde kodu değiştirebildiğinde çalışır, ancak bunu herhangi bir kodu değiştirmeden yapmak isterseniz Process Explorer'ı kullanabilirsiniz.

Sistemdeki tüm yürütme dll'lerini listeler, çalışan uygulamanızın işlem kimliğini belirlemeniz gerekebilir, ancak bu genellikle çok zor değildir.

Bu II içinde bir dll için nasıl tam bir açıklama yazdım - http://nodogmablog.bryanhogan.net/2016/09/locating-and-checking-an-executing-dll-on-a-running-web -sunucu /


Her şeyden önce, makaledeki kod oldukça IIS merkezli ve ikinci olduğunu, (Ben inanıyorum) şu anda yüklü tüm dlls verir, herhangi bir zamanda ne çalışıyor değil unutmayın.
George Mauer

Verilen örnek iis ile ilgilidir, ancak dll iis dışındaki bir işlemde çalışıyorsa aynı adımlar geçerlidir. Bu sadece işlem kimliğini belirleme meselesidir. Bunu not etmek için makaleyi güncelleyeceğim. Önerin için teşekkürler.
Bryan

2

bir windows form uygulamasında, Application.StartupPath

ancak DLL'ler ve konsol uygulamaları için kodu hatırlamak çok daha zordur ...

string slash = Path.DirectorySeparatorChar.ToString();
string root = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

root += slash;
string settingsIni = root + "settings.ini"


1

Bir yol '#' sembolünü içeriyorsa yanlış dizin elde edersiniz. Bu yüzden UriBuilder.Path ve UriBuilder kombinasyonu olan John Sibly cevabının bir modifikasyonunu kullanıyorum.

public static string AssemblyDirectory
{
    get
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        //modification of the John Sibly answer    
        string path = Uri.UnescapeDataString(uri.Path.Replace("/", "\\") + 
          uri.Fragment.Replace("/", "\\"));
        return Path.GetDirectoryName(path);
     }
}

0

Ben de bunu buldum. Web projeleri arasında birim testleri (nunit ve yeniden birleştirici test koşucusu) ; Bunun benim için işe yaradığını gördüm.

Yapı hangi yapılandırma olduğunu tespit etmek için kod arıyordum Debug/Release/CustomName. Ne yazık ki #if DEBUG. Yani birisi bunu geliştirebilirse !

Düzenlemek ve geliştirmek için çekinmeyin.

Uygulama klasörü alınıyor . Web kökleri için yararlı, testtestler klasörü almak için unittests.

public static string AppPath
{
    get
    {
        DirectoryInfo appPath = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);

        while (appPath.FullName.Contains(@"\bin\", StringComparison.CurrentCultureIgnoreCase)
                || appPath.FullName.EndsWith(@"\bin", StringComparison.CurrentCultureIgnoreCase))
        {
            appPath = appPath.Parent;
        }
        return appPath.FullName;
    }
}

Bin klasörü alınıyor: Yansıma kullanarak montajları yürütmek için kullanışlıdır. Dosyalar yapı özellikleri nedeniyle orada kopyalanırsa.

public static string BinPath
{
    get
    {
        string binPath = AppDomain.CurrentDomain.BaseDirectory;

        if (!binPath.Contains(@"\bin\", StringComparison.CurrentCultureIgnoreCase)
            && !binPath.EndsWith(@"\bin", StringComparison.CurrentCultureIgnoreCase))
        {
            binPath = Path.Combine(binPath, "bin");
            //-- Please improve this if there is a better way
            //-- Also note that apps like webapps do not have a debug or release folder. So we would just return bin.
#if DEBUG
            if (Directory.Exists(Path.Combine(binPath, "Debug"))) 
                        binPath = Path.Combine(binPath, "Debug");
#else
            if (Directory.Exists(Path.Combine(binPath, "Release"))) 
                        binPath = Path.Combine(binPath, "Release");
#endif
        }
            return binPath;
    }
}

0

Bu çalışmalı:

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
Assembly asm = Assembly.GetCallingAssembly();
String path = Path.GetDirectoryName(new Uri(asm.EscapedCodeBase).LocalPath);

string strLog4NetConfigPath = System.IO.Path.Combine(path, "log4net.config");

Bu bazı yapılandırma dosyası ile birlikte DLL dosya kitaplıkları dağıtmak için kullanıyorum (bu DLL dosyası içinden log4net kullanmaktır).


fileMapBurada ne için kullanılır?
George Mauer

0

Çözümümü konumun alınması için yeterli buluyorum.

var executingAssembly = new FileInfo((Assembly.GetExecutingAssembly().Location)).Directory.FullName;

Bu zaten en fazla işaretlenen cevaplardan biridir ve bu durumda çalışmıyor şey olarak söz konusu açıkça ifade edilir.
George Mauer

Özür dilerim bunu kaçırdı! Açıkçası tam olarak okumadım.
Tez Wingfield

0

NUnitGeçmişte de aynı davranışı yaşadım . Varsayılan olarak NUnitderlemenizi temp dizinine kopyalar. Bu davranışı NUnitayarlarda değiştirebilirsiniz:

resim açıklamasını buraya girin

Belki TestDriven.NETve MbUnitGUI aynı ayarlara sahiptir.


-3

Bin dizinine yol almak için bunu kullanın:

var i = Environment.CurrentDirectory.LastIndexOf(@"\");
var path = Environment.CurrentDirectory.Substring(0,i); 

Bu sonucu alırsınız:

"c: \ users \ ricooley \ belgeler \ visual studio 2010 \ Projects \ Windows_Test_Project \ Windows_Test_Project \ bin"


6
Path.getDirectoryName önlemek için bir neden görmüyorum
Max Keller

@MaxKeller Sebeplerini görmüyorsanız, bunun doğru olduğu anlamına gelmez. Path.GetDirectoryName'in bu alternatif yöntemi on kat daha hızlıdır.
Ruslan Veselov

-3

Web uygulaması?

Server.MapPath("~/MyDir/MyFile.ext")

2
@christiandev bu bir cevap ama belki de yanlış soruya bir cevap gibi görünüyor. Sorudan, bunun bir web uygulaması değil, MbUnit ile çalıştırılan bir montaj olduğu oldukça açıktır. Bununla birlikte, Asp.Net gölge kopyalaması nedeniyle cevap hala gerçekten doğru değil (bu soruya inen birinin aradığı şey muhtemelen akla gelebilir).
George Mauer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.