समाधान एक ऐसा लक्ष्य बनाना है जो आपकी फ़ाइलों को संकलित आइटम समूह में जोड़ता है बल्कि उन्हें आपकी .csproj फ़ाइल में स्पष्ट रूप से जोड़ने के बजाय जोड़ता है। इस तरह इंटेलिसेंस उन्हें देखेगा और उन्हें आपके निष्पादन योग्य में संकलित किया जाएगा, लेकिन वे विजुअल स्टूडियो में दिखाई नहीं देंगे।
सरल उदाहरण
तुम भी सुनिश्चित करें कि आपके लक्ष्य CoreCompileDependsOn
संपत्ति में जोड़ा जाता है तो यह संकलक रन से पहले निष्पादित करेंगे बनाने की जरूरत है।
<PropertyGroup>
<CoreCompileDependsOn>$(CoreCompileDependsOn);AddToolOutput</CoreCompileDependsOn>
</PropertyGroup>
<Target Name="AddToolOutput">
<ItemGroup>
<Compile Include="HiddenFile.cs" />
</ItemGroup>
</Target>
आप अपने .csproj फ़ाइल के नीचे करने के लिए इस जोड़ देते हैं तो (बस से पहले </Project>
), अपने "HiddenFile.cs" अपने संकलन में भले ही शामिल किया जाएगा:
यहाँ एक बहुत ही सरल उदाहरण है यह विजुअल स्टूडियो में दिखाई नहीं देता है।
का उपयोग करते हुए एक अलग .targets
इसके बजाय इसे सीधे .csproj फ़ाइल में रखने की फाइल, आप आम तौर पर यह एक अलग .targets फ़ाइल में रखा जाएगा से घिरा हुआ:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
</Project>
और आयात <Import Project="MyTool.targets">
के साथ अपने .csproj में। ए। टाइटल्स फ़ाइल को एक-ऑफ केस के लिए भी अनुशंसित किया जाता है क्योंकि यह विजुअल स्टूडियो द्वारा बनाए गए .csproj में सामान से अपना कस्टम कोड अलग करता है।
उत्पन्न फ़ाइल नाम (रों)
का निर्माण आप एक सामान्यीकृत उपकरण का निर्माण कर रहे हैं और/या एक अलग .targets फ़ाइल का उपयोग, तो आप शायद नहीं स्पष्ट रूप से प्रत्येक छिपा फ़ाइल सूचीबद्ध करना चाहते हैं। इसके बजाय आप प्रोजेक्ट में अन्य सेटिंग्स से छिपा फ़ाइल नाम बनाना चाहते हैं।उदाहरण के लिए यदि आप सभी संसाधन फ़ाइलें "obj" निर्देशिका में इसी उपकरण उत्पन्न फ़ाइलों करना चाहते हैं, अपने लक्ष्य होगा:
<Target Name="AddToolOutput">
<ItemGroup>
<Compile Include="@(Resource->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')" />
</ItemGroup>
</Target>
"IntermediateOutputPath" संपत्ति क्या हम सब "obj" निर्देशिका के रूप में जानते है , लेकिन अगर आपके .targets के अंतिम उपयोगकर्ता ने इसे अनुकूलित किया है तो आपकी इंटरमीडिएट फाइलें एक ही स्थान पर मिल जाएंगी। यदि आप अपनी जेनरेट की गई फ़ाइलों को मुख्य प्रोजेक्ट निर्देशिका में पसंद करते हैं और "obj" निर्देशिका में नहीं, तो आप इसे छोड़ सकते हैं।
यदि आप अपने कस्टम उपकरण द्वारा संसाधित किए जाने वाले मौजूदा आइटम प्रकार की फ़ाइलों में से केवल कुछ चाहते हैं? उदाहरण के लिए, आप ".xyz" एक्सटेंशन के साथ सभी पेज और संसाधन फ़ाइलों के लिए फ़ाइलें जेनरेट करना चाह सकते हैं।
<Target Name="AddToolOutput">
<ItemGroup>
<MyToolFiles Include="@(Page);@(Resource)" Condition="'%(Extension)'=='.xyz' />
<Compile Include="@(MyToolFiles->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')"/>
</ItemGroup>
</Target>
ध्यान दें कि आप एक शीर्ष स्तर ItemGroup में% (एक्सटेंशन) की तरह मेटाडाटा सिंटैक्स का उपयोग नहीं कर सकते हैं लेकिन आप एक लक्ष्य के भीतर ऐसा कर सकते हैं।
(उर्फ कार्रवाई का निर्माण)
ऐसे पृष्ठ, संसाधन, या संकलित (विजुअल स्टूडियो कॉल इस "एक्शन बनाएँ") के रूप में एक आइटम पहले प्रकार है कि इसके बाद के संस्करण की प्रक्रिया फ़ाइलें एक कस्टम आइटम प्रकार का उपयोग करना। यदि आपके आइटम एक नई तरह की फाइल हैं तो आप अपने स्वयं के कस्टम आइटम प्रकार का उपयोग कर सकते हैं। उदाहरण के लिए यदि आपके इनपुट फ़ाइलें हैं कहा जाता है "xyz" फाइलें, अपनी परियोजना फ़ाइल एक वैध आइटम प्रकार के रूप में परिभाषित कर सकते हैं "xyz":
<ItemGroup>
<AvailableItemName Include="Xyz" />
</ItemGroup>
जिसके बाद दृश्य स्टूडियो आप "xyz" कार्रवाई बिल्ड में चयन करने के लिए अनुमति देगा फ़ाइल के गुणों में, इस में जिसके परिणामस्वरूप अपने .csproj में जोड़ा जा रहा:
<ItemGroup>
<Xyz Include="Something.xyz" />
</ItemGroup>
अब आप उपकरण उत्पादन के लिए फ़ाइल नाम बनाने के लिए "xyz" आइटम प्रकार का उपयोग कर सकते हैं, तो हम "संसाधन" के साथ पहले किया था बस के रूप में आइटम का प्रकार:
<Target Name="AddToolOutput">
<ItemGroup>
<Compile Include="@(Xyz->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')" />
</ItemGroup>
</Target>
कस्टम आइटम प्रकार का उपयोग करते समय आप अपने आइटम को किसी अन्य आइटम प्रकार (उर्फ बिल्ड एक्शन) पर मैप करके अंतर्निर्मित तंत्र द्वारा भी प्रबंधित कर सकते हैं। यह उपयोगी है अगर आपकी "Xyz" फ़ाइलें वास्तव में .cs फ़ाइलें या .xaml हैं या यदि उन्हें
एम्बेडेड स्रोतों की आवश्यकता है। उदाहरण के लिए आप के साथ Xyz की "का निर्माण कार्य" सभी फाइलों को पैदा कर सकता है भी संकलित करने के लिए किया जा:
<ItemGroup>
<Compile Include="@(Xyz)" />
</ItemGroup>
या अगर आपके "xyz" स्रोत फ़ाइलें एम्बेडेड संसाधनों के रूप में संग्रहित किया जाना चाहिए, तो आप इसे इस तरह से व्यक्त कर सकते हैं:
<ItemGroup>
<EmbeddedResource Include="@(Xyz)" />
</ItemGroup>
ध्यान दें कि यदि आप इसे लक्ष्य के अंदर डालते हैं तो दूसरा उदाहरण काम नहीं करेगा, क्योंकि मूल संकलन से पहले लक्ष्य का मूल्यांकन नहीं किया जाता है। इस काम को एक लक्ष्य के अंदर बनाने के लिए आपको CoreCompileDependsOn की बजाय PrepareForBuildDependsOn संपत्ति में लक्ष्य नाम सूचीबद्ध करना होगा।
MSBuild
से अपने कस्टम कोड जनरेटर लागू एक .targets फ़ाइल बनाने के रूप में, आप MSBuild से सीधे अपने उपकरण लागू करने के बजाय एक अलग पूर्व निर्माण घटना या दृश्य स्टूडियो के त्रुटिपूर्ण उपयोग करने पर विचार हो सकता है के रूप में दूर चली गई करने के बाद "कस्टम उपकरण" तंत्र।
ऐसा करने के लिए:
- Microsoft.Build.Framework
- के लिए एक संदर्भ के साथ एक कक्षा लाइब्रेरी प्रोजेक्ट बनाएं अपने कस्टम कोड जनरेटर लागू करने के लिए
- एक वर्ग है कि ITask लागू करता जोड़े कोड जोड़ें, और निष्पादित विधि में अपने कस्टम कोड फोन जनरेटर
- अपने .targets फाइल करने के लिए एक
UsingTask
तत्व जोड़ें, और अपने लक्ष्य में अपना नया कार्य के लिए एक कॉल जोड़ने
यहाँ सब आप ITask लागू करने की आवश्यकता है:
public class GenerateCodeFromXyzFiles : ITask
{
public IBuildEngine BuildEngine { get; set; }
public ITaskHost HostObject { get; set; }
public ITaskItem[] InputFiles { get; set; }
public ITaskItem[] OutputFiles { get; set; }
public bool Execute()
{
for(int i=0; i<InputFiles.Length; i++)
File.WriteAllText(OutputFiles[i].ItemSpec,
ProcessXyzFile(
File.ReadAllText(InputFiles[i].ItemSpec)));
}
private string ProcessXyzFile(string xyzFileContents)
{
// Process file and return generated code
}
}
और यहाँ UsingTask तत्व और एक लक्ष्य है कि यह कहता है: कि इस लक्ष्य के आउटपुट तत्व उत्पादन की सूची देता है
<UsingTask TaskName="MyNamespace.GenerateCodeFromXyzFiles" AssemblyFile="MyTaskProject.dll" />
<Target Name="GenerateToolOutput">
<GenerateCodeFromXyzFiles
InputFiles="@(Xyz)"
OutputFiles="@(Xyz->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')">
<Output TaskParameter="OutputFiles" ItemGroup="Compile" />
</GenerateCodeFromXyzFiles>
</Target>
नोट सीधे संकलन में फ़ाइलें, इसलिए ऐसा करने के लिए एक अलग आइटम समूह का उपयोग करने की आवश्यकता नहीं है।
कितने साल "कस्टम उपकरण" तंत्र से दोषपूर्ण है और क्यों है उपयोग करने के लिए नहीं यह
दृश्य स्टूडियो के "कस्टम उपकरण" तंत्र पर एक नोट: नेट फ्रेमवर्क 1.x हम MSBuild नहीं था, इसलिए हमें अपनी परियोजनाओं के निर्माण के लिए विजुअल स्टूडियो पर भरोसा करना पड़ा। जेनरेट कोड पर इंटेलिसेंस प्राप्त करने के लिए, विजुअल स्टूडियो में "कस्टम टूल" नामक एक तंत्र था जिसे फ़ाइल पर प्रॉपर्टी विंडो में सेट किया जा सकता है। तंत्र मूल रूप से कई तरीकों से त्रुटिपूर्ण था, यही कारण है कि इसे एमएसबिल्ड लक्ष्यों के साथ बदल दिया गया था। "कस्टम उपकरण" सुविधा के साथ समस्याओं में से कुछ इस प्रकार थे:
- एक "कस्टम उपकरण" उत्पन्न फ़ाइल निर्माण करती है जब भी फ़ाइल संपादित और सहेजा जाता है, परियोजना संकलित किया गया है जब नहीं। इसका अर्थ यह है कि फ़ाइल को बाहरी रूप से संशोधित करने वाला कोई भी (जैसे कि संशोधन नियंत्रण प्रणाली) जेनरेट की गई फ़ाइल को अपडेट नहीं करता है और आपको अक्सर अपने निष्पादन योग्य में बालों का कोड मिलता है।
- "कस्टम टूल" का आउटपुट आपके स्रोत पेड़ के साथ भेजना था जब तक आपके प्राप्तकर्ता के पास विजुअल स्टूडियो और आपका "कस्टम टूल" दोनों न हो।
- रजिस्ट्री में "कस्टम टूल" स्थापित होना था और इसे प्रोजेक्ट फ़ाइल से संदर्भित नहीं किया जा सका।
- "कस्टम टूल" का आउटपुट "obj" निर्देशिका में संग्रहीत नहीं है।
यदि आप पुराने "कस्टम टूल" सुविधा का उपयोग कर रहे हैं, तो मैं दृढ़ता से अनुशंसा करता हूं कि आप एक एमएसबिल्ड कार्य का उपयोग करने के लिए स्विच करें। यह इंटेलिजेंस के साथ अच्छी तरह से काम करता है और आपको विजुअल स्टूडियो को स्थापित किए बिना अपनी परियोजना बनाने की अनुमति देता है (आपको केवल नेट फ्रेमवर्क की आवश्यकता है)।
आपका कस्टम बिल्ड कार्य कब चलेंगे?
सामान्य तौर पर अपने कस्टम निर्माण कार्य चलेंगे:
- पृष्ठभूमि में जब दृश्य स्टूडियो समाधान को खोलता है, अगर उत्पन्न फ़ाइल किसी भी समय आप एक को बचाने पृष्ठभूमि में अप टू डेट
- के लिए नहीं है दृश्य स्टूडियो
- किसी भी समय आप का निर्माण, अगर उत्पन्न फ़ाइल तारीख
- किसी भी समय के लिए नहीं है में इनपुट फ़ाइलों की आप के पुनर्निर्माण
अधिक सटीक होना: जब दृश्य स्टूडियो शुरू होता है और हर बार किसी भी फ़ाइल दृश्य स्टूडियो में सहेजा जाता है
- एक IntelliSense वृद्धिशील निर्माण चलाया जाता है। यह जनरेटर चलाएगा यदि आउटपुट फ़ाइल गायब है तो इनपुट इनपुट में से कोई भी जेनरेटर आउटपुट से नया है।
- जब भी आप विजुअल स्टूडियो (मेनू विकल्प और F5 दबाकर) में किसी भी "बिल्ड" या "रन" कमांड का उपयोग करते हैं, या जब आप कमांड लाइन से "MSBuild" चलाते हैं तो नियमित वृद्धिशील बिल्ड चलाया जाता है। IntelliSense वृद्धिशील बिल्ड की तरह, यह केवल जनरेटर को चलाएगा यदि जेनरेट की गई फ़ाइल
- जब भी आप विजुअल स्टूडियो में "पुनर्निर्माण" आदेशों में से किसी एक का उपयोग करते हैं, या जब आप " एमएसबिल्ड/टी: कमांड लाइन से "पुनर्निर्माण"। यदि कोई इनपुट या आउटपुट होता है तो यह हमेशा आपके जनरेटर को चलाएगा।
आप अपने जनरेटर को अन्य समय चलाने के लिए मजबूर करना चाहते हैं, जैसे कि जब कुछ पर्यावरण परिवर्तनीय परिवर्तन होते हैं, या पृष्ठभूमि में सिंक्रनाइज़ रूप से चलाने के लिए मजबूर करते हैं।
पैदा करने के लिए जनरेटर फिर से चलाने के लिए भले ही कोई भी इनपुट फ़ाइलों को बदल दिया है, सबसे अच्छा तरीका है अपने लक्ष्य जो एक डमी इनपुट "obj" निर्देशिका में संग्रहीत फ़ाइल है के लिए एक अतिरिक्त इनपुट को जोड़ने के लिए आमतौर पर है। फिर जब भी कोई पर्यावरण चर या कुछ बाहरी सेटिंग बदलती है जो आपके जेनरेटर टूल को फिर से चलाने के लिए मजबूर कर दे, तो बस इस फ़ाइल को स्पर्श करें (यानी इसे बनाएं या इसकी संशोधित तिथि अपडेट करें)।
जनरेटर को पृष्ठभूमि में चलाने के लिए इंटेलिसेन्स की प्रतीक्षा करने के बजाय सिंक्रनाइज़ करने के लिए मजबूर करने के लिए, बस अपना विशेष लक्ष्य बनाने के लिए एमएसबिल्ड का उपयोग करें। यह "एमएसबिल्ड/टी: जेनरेट टूलऑटपुट" निष्पादित करने जितना सरल हो सकता है, या वीएसआईपी कस्टम बिल्ड लक्ष्यों को कॉल करने के लिए एक अंतर्निहित तरीका प्रदान कर सकता है। वैकल्पिक रूप से आप बस बिल्ड कमांड का आह्वान कर सकते हैं और इसे पूरा करने के लिए प्रतीक्षा कर सकते हैं।
ध्यान दें कि इस खंड में "इनपुट फ़ाइलें" लक्ष्य तत्व के "इनपुट" विशेषता में जो भी सूचीबद्ध है उसे संदर्भित करती है।
अंतिम नोटों
आप दृश्य स्टूडियो से चेतावनी है कि यह अपने कस्टम उपकरण .targets फ़ाइल पर भरोसा करना है कि क्या पता नहीं है हो सकता है। इसे ठीक करने के लिए, इसे HKEY_LOCAL_MACHINE \ सॉफ़्टवेयर \ Microsoft \ VisualStudio \ 9.0 \ MSBuild \ SafeImports रजिस्ट्री कुंजी में जोड़ें।
यहां एक वास्तविक सारांश का सारांश दिया गया है।लक्ष्य फ़ाइल स्थान में सभी टुकड़ों के साथ दिखाई देगा:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CoreCompileDependsOn>$(CoreCompileDependsOn);GenerateToolOutput</CoreCompileDependsOn>
</PropertyGroup>
<UsingTask TaskName="MyNamespace.GenerateCodeFromXyzFiles" AssemblyFile="MyTaskProject.dll" />
<Target Name="GenerateToolOutput" Inputs="@(Xyz)" Outputs="@(Xyz->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')">
<GenerateCodeFromXyzFiles
InputFiles="@(Xyz)"
OutputFiles="@(Xyz->'$(IntermediateOutputPath)%(FileName)%(Extension).g.cs')">
<Output TaskParameter="OutputFiles" ItemGroup="Compile" />
</GenerateCodeFromXyzFiles>
</Target>
</Project>
कृपया मुझे पता यदि आप कोई प्रश्न या वहाँ यहाँ कुछ भी आप समझ में नहीं आया है अगर करते हैं।
जहां (सापेक्ष स्रोत फ़ाइलों के लिए) आप उत्पन्न फ़ाइलों बचत कर रहे हैं? – luke
आउटपुट निर्देशिका इनपुट निर्देशिका के समान है। – jaws
जब आप कहते हैं कि डब्ल्यूपीएफ कोड-बैक फाइलें छिपी हुई हैं तो आपका क्या मतलब है? यदि मैं एक WPF अनुप्रयोग बनाता हूं तो मुझे MainWindow.xaml नाम की एक फ़ाइल मिलती है, जिसे मैं कोड-बैक फ़ाइल, MainWindow.xaml.cs पर विश्वास करने के लिए विस्तारित किया जा सकता हूं। – ErikHeemskerk