2008-10-07 10 views
53

मैं एमएसबिल्ड को <Message /> में मूल्यांकन और प्रिंट करने के लिए कैसे प्राप्त कर सकता हूं एक सापेक्ष पथ दिया गया एक पूर्ण पथ?मैं रिश्तेदार पथ दिए जाने पर पूर्ण पथ का मूल्यांकन और प्रिंट करने के लिए एमएसबीयूआईएलडी कैसे प्राप्त कर सकता हूं?

प्रॉपर्टी समूह

<Source_Dir>..\..\..\Public\Server\</Source_Dir> 
<Program_Dir>c:\Program Files (x86)\Program\</Program_Dir> 

टास्क

<Message Importance="low" Text="Copying '$(Source_Dir.FullPath)' to '$(Program_Dir)'" /> 

आउटपुट

प्रतिलिपि बनाई जा रही '' में ग: \ Program Files (x86) \ कार्यक्रम \ '

+0

मुझे लगता है कि फुलपाथ मेटाडाटा केवल आइटम पर लागू होता है, न कि गुण। – lesscode

+0

मुझे लगता है कि आप सही हैं, किसी को संपत्ति से पूर्ण/पूर्ण पथ तक पहुंचने का कोई तरीका पता है? –

+1

आप $ (ProjectDir) $ (Source_Dir), का उपयोग करके "थोड़े" वहां जा सकते हैं, लेकिन आपके पास अनावश्यक '..' – lesscode

उत्तर

86

MSBuild 4.0 में, सबसे आसान तरीका है :

$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)\your\path')) 

इस विधि से काम करता है, भले ही स्क्रिप्ट <Import> एड में है एक और लिपि; पथ उपर्युक्त कोड वाली फ़ाइल से संबंधित है।

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
     DefaultTargets="Test" 
     ToolsVersion="3.5"> 
    <PropertyGroup> 
    <Source_Dir>..\..\..\Public\Server\</Source_Dir> 
    <Program_Dir>c:\Program Files (x86)\Program\</Program_Dir> 
    </PropertyGroup> 

    <Target Name="Test"> 
    <ConvertToAbsolutePath Paths="$(Source_Dir)"> 
     <Output TaskParameter="AbsolutePaths" PropertyName="Source_Dir_Abs"/> 
    </ConvertToAbsolutePath> 
    <Message Text='Copying "$(Source_Dir_Abs)" to "$(Program_Dir)".' /> 
    </Target> 
</Project> 

प्रासंगिक उत्पादन:


(Aaron's answer के साथ-साथ Sayed's answer के अंतिम भाग से समेकित) MSBuild 3.5 में, आप ConvertToAbsolutePath कार्य का उपयोग कर सकते

Project "P:\software\perforce1\main\XxxxxxXxxx\Xxxxx.proj" on node 0 (default targets). 
    Copying "P:\software\Public\Server\" to "c:\Program Files (x86)\Program\". 

यदि आप मुझसे पूछें तो थोड़ा लंबा हवादार, लेकिन यह काम करता है। यह "मूल" प्रोजेक्ट फ़ाइल के सापेक्ष होगा, इसलिए यदि <Import> एड प्राप्त होने वाली फ़ाइल के अंदर रखा गया है, तो यह उस फ़ाइल के सापेक्ष नहीं होगा।


MSBuild 2.0 में, एक दृष्टिकोण है जो हल नहीं होती है ".."। लेकिन यह सिर्फ एक निरपेक्ष पथ की तरह व्यवहार करता है:

<PropertyGroup> 
    <Source_Dir_Abs>$(MSBuildProjectDirectory)\$(Source_Dir)</Source_Dir_Abs> 
</PropertyGroup> 

$(MSBuildProjectDirectory) सुरक्षित संपत्ति हमेशा स्क्रिप्ट है कि इस संदर्भ है की निर्देशिका है।

यह "मूल" प्रोजेक्ट फ़ाइल के सापेक्ष भी होगा, इसलिए यदि <Import> एड प्राप्त होने वाली फ़ाइल के अंदर रखा गया है, तो यह उस फ़ाइल के सापेक्ष नहीं होगा।

+0

'[System.IO.Path] :: GetFullPath से सावधान रहें '। मैं विजुअल स्टूडियो में एक त्रुटि निर्माण में भाग गया क्योंकि msbuild में वर्तमान कार्यशील निर्देशिका 'सी: \ विंडोज \ System32' थी। 'GetFullPath' प्रोजेक्ट निर्देशिका की बजाय कार्य निर्देशिका के सापेक्ष हल करता है। –

+0

@ChrisChilvers दुर्भाग्यपूर्ण है। पिछली बार मैंने इसका परीक्षण किया (स्वीकार्य रूप से बहुत समय पहले), यह कोड युक्त फाइल के सापेक्ष था। –

+0

यह बैकट्रैसिंग '.. \ .. \ your \ path' शैली पथ के लिए भी काम करता है। यह भी ध्यान दें कि '$ (MSBuildThisFileDirectory)' मैक्रो में पहले से ही एक पिछला स्लैश शामिल है, इसलिए आपको प्रमुख स्लैश i के बिना 'your \ path' निर्दिष्ट करना होगा।ई '$ (MSBuildThisFileDirectory) आपके \ path'। एक मामला जहां यह मायने रखता है जब आप माइक्रोसॉफ्ट यूनिट परीक्षण फ्रेमवर्क टेस्ट के लिए 'आउटडियर' के लिए इसका इस्तेमाल करते हैं, जब आप परीक्षण चलाने की कोशिश करते हैं तो यह निर्मित खोजने के लिए समेकित पथ में '\\\' का मूल्यांकन करने में असमर्थ होगा dll। –

6

वेन सही है कि प्रसिद्ध मेटाडाटा गुणों पर लागू नहीं होता है - केवल वस्तुओं के लिए। "MSBuildProjectDirectory" जैसे गुणों का उपयोग करना काम करेगा, लेकिन मुझे पूर्ण पथ को हल करने के लिए अंतर्निहित तरीके से अवगत नहीं है।

एक और विकल्प एक सरल, कस्टम कार्य लिखना है जो एक सापेक्ष पथ लेगा और पूरी तरह हल किए गए पथ को थूक देगा। यह कुछ इस तरह दिखेगा:

public class ResolveRelativePath : Task 
{ 
    [Required] 
    public string RelativePath { get; set; } 

    [Output] 
    public string FullPath { get; private set; } 

    public override bool Execute() 
    { 
     try 
     { 
      DirectoryInfo dirInfo = new DirectoryInfo(RelativePath); 
      FullPath = dirInfo.FullName; 
     } 
     catch (Exception ex) 
     { 
      Log.LogErrorFromException(ex); 
     } 
     return !Log.HasLoggedErrors; 
    } 
} 

और अपने MSBuild लाइनों लगेगा कुछ की तरह:

<PropertyGroup> 
    <TaskAssembly>D:\BuildTasks\Build.Tasks.dll</TaskAssembly> 
    <Source_Dir>..\..\..\Public\Server\</Source_Dir> 
    <Program_Dir>c:\Program Files (x86)\Program\</Program_Dir> 
</PropertyGroup> 
<UsingTask AssemblyFile="$(TaskAssembly)" TaskName="ResolveRelativePath" /> 

<Target Name="Default"> 
    <ResolveRelativePath RelativePath="$(Source_Dir)"> 
    <Output TaskParameter="FullPath" PropertyName="_FullPath" /> 
    </ResolveRelativePath> 
    <Message Importance="low" Text="Copying '$(_FullPath)' to '$(Program_Dir)'" /> 
</Target> 
+4

दोस्त होगा, मैंने इस टुकड़े से एमएस टास्क बनाने के तरीके के बारे में और अधिक सीखा है ऊपर कोड, तो मैं कभी भी MSBuild दस्तावेज में है। धन्यवाद! :-) – evilhomer

5

तो आप प्रॉपर्टी है, जो संभव नहीं है के माध्यम से एक आइटम मेटाडाटा संपत्ति का उपयोग करने की कोशिश कर रहे हैं। क्या आप क्या करना चाहते कुछ इस तरह है:

<PropertyGroup> 
    <Program_Dir>c:\Program Files (x86)\Program\</Program_Dir> 
</PropertyGroup> 
<ItemGroup> 
    <Source_Dir Include="..\Desktop"/> 
</ItemGroup>  
<Target Name="BuildAll"> 
    <Message Text="Copying '%(Source_Dir.FullPath)' to '$(Program_Dir)'" /> 
</Target> 

कौन सा उत्पादन उत्पन्न होगा के रूप में:

Copying 'C:\Users\sdorman\Desktop' to 'c:\Program Files (x86)\Program\' 

(स्क्रिप्ट मेरे दस्तावेज़ फ़ोल्डर से चला गया था, इसलिए .. \ डेस्कटॉप सही रिश्तेदार मार्ग है मेरे डेस्कटॉप पर जाने के लिए।)

अपने मामले में, ".. \ डेस्कटॉप" को "...... \ Public \ Server" के साथ Source_Dir आइटम में बदलें और आपको सभी सेट होना चाहिए।

+0

+1 यह अच्छी तरह से काम करता है और मैं (दूसरों की तरह) यहां एक आइटम समूह को कैननिकलाइज़ करने का एक तरीका खोज रहा हूं (एक बैच मानते हुए और एक नए आइटम समूह को प्रतिलिपि बनाना आवश्यक था) - आपके द्वारा दिखाए गए सिंटैक्स को बिना किसी भ्रम के । मैं अब 'फुलपाथ' के बारे में भूल गया था [अच्छी तरह से ज्ञात मेटाडाटा] (http://msdn.microsoft.com/en-us/library/ms164313.aspx) –

4

यदि आपको गुणों को आइटम में कनवर्ट करने की आवश्यकता है तो आपके पास दो विकल्प हैं। MSBuild 2 के साथ, आप CreateItem कार्य

<Target Name='Build'> 
    <CreateItem Include='$(Source_Dir)'> 
     <Output ItemName='SRCDIR' TaskParameter='Include' /> 
    </CreateItem> 

और MSBuild 3.5 के साथ आप के अंदर ItemGroups हो सकता है निम्न का उपयोग कर सकते एक टास्क

<Target Name='Build'> 
    <ItemGroup> 
     <SRCDIR2 Include='$(Source_Dir)' /> 
    </ItemGroup> 
    <Message Text="%(SRCDIR2.FullPath)" /> 
    <Message Text="%(SRCDIR.FullPath)" /> 
    </Target> 
31

एमएसबिल्ड 4.0 जोड़ा गया Property Functions जो आपको कुछ .NET सिस्टम डीएलएस में स्थिर कार्यों में कॉल करने की अनुमति देता है। संपत्ति कार्यों के बारे में वास्तव में एक अच्छी बात यह है कि वे एक लक्ष्य के पक्ष का मूल्यांकन करेंगे।

<PropertyGroup> 
    <Source_Dir>$([System.IO.Path]::GetFullPath('..\..\..\Public\Server\'))</Source_Dir> 
</PropertyGroup> 

वाक्य रचना एक छोटे बदसूरत लेकिन बहुत शक्तिशाली है:

एक पूर्ण पथ आप System.IO.Path.GetFullPath उपयोग कर सकते हैं जब बहुत की तरह एक संपत्ति को परिभाषित करने का मूल्यांकन करने के।

+0

+1 ओह मैन। यह भी खूब रही! ठीक वही जो मेरे द्वारा खोजा जा रहा था। धन्यवाद। – Asaf

+0

ग्रेट टिप। धन्यवाद। –

+0

यह परियोजना फ़ाइल को अपेक्षाकृत पथ (जहां तक ​​मैं देखता हूं) अपेक्षाकृत पथ का मूल्यांकन करता हूं, जहां संपत्ति परिभाषित की जाती है, जो कि जब आप अन्य संपत्तियों में उस संपत्ति को शामिल करना चाहते हैं तो बहुत अच्छा होता है। मेरे लिए, यह एकदम सही समाधान था। –