PowerShell में विधानसभाओं को कैसे लोड करें?


153

निम्न PowerShell कोड

#Get a server object which corresponds to the default instance
$srv = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Server
... rest of the script ...

निम्न त्रुटि संदेश देता है:

New-Object : Cannot find type [Microsoft.SqlServer.Management.SMO.Server]: make sure 
the assembly containing this type is loaded.
At C:\Users\sortelyn\ ... \tools\sql_express_backup\backup.ps1:6  char:8
+ $srv = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Server
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand

इंटरनेट पर हर उत्तर लिखता है कि मुझे असेंबली लोड करना है - अच्छी तरह से मुझे यकीन है कि मैं त्रुटि संदेश से पढ़ सकता हूं :-) - सवाल यह है:

आप असेंबली को कैसे लोड करते हैं और स्क्रिप्ट काम करते हैं?

जवाबों:


179

LoadWithPartialNameपदावनत कर दिया गया है। PowerShell V3 के लिए अनुशंसित समाधान Add-Typecmdlet का उपयोग करना है जैसे:

Add-Type -Path 'C:\Program Files\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.Smo.dll'

कई अलग-अलग संस्करण हैं और आप एक विशेष संस्करण चुनना चाहते हैं। :-)


1
ठीक है मैं PowerShell3 का उपयोग करता हूं - इनमें शामिल हैं आदेश बहुत जटिल लगते हैं। मैं बस "फ़ाइल नाम शामिल करना" जैसी कुछ उम्मीद करूंगा।
बैक्सटर

6
PowerShell केस-असंवेदनशील है (जब तक कि आप इसे केस-संवेदी जैसे -cmatch, -ceq के साथ संवेदनशील होने के लिए नहीं कहते)। तो कमांड नाम और मापदंडों पर आवरण कोई फर्क नहीं पड़ता।
कीथ हिल

5
हाँ। msdn.microsoft.com/en-us/library/12xc5368(v=vs.110).aspx शीर्ष पर नोट देखें - This API is now obsolete. बेशक, यह लोगों को इसका उपयोग करने से नहीं रोकता है।
कीथ हिल

2
हालांकि यह तकनीकी रूप से सही LoadWithPartialNameहै जिसे हटा दिया गया है, कारण (जैसा कि blogs.msdn.com/b/suzcook/archive/2003/05/30/57159.aspx में उल्लिखित है ) स्पष्ट रूप से एक इंटरैक्टिव Pisshell सत्र के लिए लागू नहीं होते हैं। मेरा सुझाव है कि आप ध्यान दें कि एपीआई इंटरैक्टिव पॉवरशेल उपयोग के लिए ठीक है।
मीका विडेनमैन

ज्यादातर समय, मुझे एसएमओ असेंबली से कोई समस्या नहीं है, लेकिन कभी-कभी मुझे पावरशेल को मारने की आवश्यकता होती है और जब मैं करता हूं, तो मुझे एसएमओ लोडिंग मुद्दे होने लगते हैं। ऐड-टाइप -पैथ जोड़ने से यह ठीक हो जाता है।
निकोलस डी फोंटेनै

73
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")

8
यह एक प्रतिस्थापन के बिना पदावनत करने के लिए बहुत उपयोगी है! मेरी टीम 2008 और 2012 के क्लाइंट टूल के मिश्रण का उपयोग करती है। अनाड़ी संस्करण-पतन तर्क सहित मेरी सभी टीम के लिए मेरे PowerShell स्क्रिप्ट को काम करने का यह एकमात्र तरीका है।
इयान सैमुअल मैकलीन एल्डर

4
Out-Nullयदि आप सामान को गूंजना नहीं चाहते हैं तो आप आउटपुट को पाइप कर सकते हैं ।
इयान सैमुअल मैकलीन एल्डर

3
@ बैक्सटर - आपको इस उत्तर को स्वीकार करना चाहिए या कीथ को और इस प्रश्न का उत्तर देना चाहिए।
जयकुल

3
मैं [void] [System.Reflection.Assembly] :: LoadWithPartialName ("Microsoft.SqlServer.Smo") का उपयोग करता हूं
Soeren L. Nielsen

@IainElder "अनाड़ी संस्करण-पतन तर्क" आप कहते हैं कि जब तक आप संस्करण असंगति में नहीं चलते हैं! यह कहना मुश्किल नहीं है Add-Type -Path [...]; if (!$?) { Add-Type -Path [...] } elseif [...]
बेकन बिट्स

44

अधिकांश लोग अब तक जानते हैं कि System.Reflection.Assembly.LoadWithPartialNameयह पदावनत है, लेकिन यह पता चला है कि Add-Type -AssemblyName Microsoft.VisualBasic इससे बेहतर व्यवहार नहीं हैLoadWithPartialName :

अपने सिस्टम के संदर्भ में आपके अनुरोध को पार्स करने का कोई प्रयास करने के बजाय, [ऐड-टाइप] "आंशिक नाम" को "पूर्ण नाम" में अनुवाद करने के लिए एक स्थिर, आंतरिक तालिका को देखता है।

यदि आपका "आंशिक नाम" उनकी तालिका में प्रकट नहीं होता है, तो आपकी स्क्रिप्ट विफल हो जाएगी।

यदि आपके पास अपने कंप्यूटर पर असेंबली के कई संस्करण स्थापित हैं, तो उनके बीच चयन करने के लिए कोई बुद्धिमान एल्गोरिथ्म नहीं है। आपको उनकी तालिका में जो भी दिखाई देने वाला है, संभवत: पुराना, पुराना है।

यदि आपके द्वारा इंस्टॉल किए गए संस्करण तालिका में अप्रचलित की तुलना में सभी नए हैं, तो आपकी स्क्रिप्ट विफल हो जाएगी।

ऐड-टाइप के पास "आंशिक नामों" की तरह कोई बुद्धिमान पार्सर नहीं है .LoadWithPartialNames

Microsoft क्या कहता है कि आप वास्तव में ऐसा करने वाले हैं:

Add-Type -AssemblyName 'Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'

या, यदि आप रास्ता जानते हैं, तो कुछ इस तरह से:

Add-Type -Path 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualBasic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualBasic.dll'

विधानसभा के लिए दिए गए लंबे नाम को मजबूत नाम के रूप में जाना जाता है , जो संस्करण और असेंबली दोनों के लिए अद्वितीय है, और कभी-कभी पूर्ण नाम के रूप में भी जाना जाता है।

लेकिन यह एक अनुत्तरित कुछ सवालों को छोड़ देता है:

  1. मैं एक आंशिक रूप से दिए गए आंशिक नाम के साथ अपने सिस्टम पर वास्तव में लोड होने वाले मजबूत नाम का निर्धारण कैसे करूं?

    [System.Reflection.Assembly]::LoadWithPartialName($TypeName).Location; [System.Reflection.Assembly]::LoadWithPartialName($TypeName).FullName;

ये भी काम करना चाहिए:

Add-Type -AssemblyName $TypeName -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
  1. अगर मैं चाहता हूं कि मेरी स्क्रिप्ट हमेशा एक .dll के एक विशिष्ट संस्करण का उपयोग करें, लेकिन मैं निश्चित नहीं हो सकता कि यह कहाँ स्थापित है, तो मैं कैसे निर्धारित करूं कि .dll से मजबूत नाम क्या है?

    [System.Reflection.AssemblyName]::GetAssemblyName($Path).FullName;

या:

Add-Type $Path -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
  1. यदि मैं मजबूत नाम जानता हूं, तो मैं .dll पथ कैसे निर्धारित करूं?

    [Reflection.Assembly]::Load('Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a').Location;

  2. और, एक समान नस पर, अगर मुझे पता है कि मैं जो उपयोग कर रहा हूं उसका प्रकार क्या है, मुझे कैसे पता चलेगा कि यह किस विधानसभा से आ रहा है?

    [Reflection.Assembly]::GetAssembly([Type]).Location [Reflection.Assembly]::GetAssembly([Type]).FullName

  3. मैं कैसे देख सकता हूं कि विधानसभाएं उपलब्ध हैं?

मैं GAC पॉवरशेल मॉड्यूल का सुझाव देता हूं । Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullNameबहुत अच्छा काम करता है।

  1. मैं उस सूची को कैसे देख सकता हूं जो Add-Typeउपयोग करती है?

यह थोड़ा अधिक जटिल है। मैं यह वर्णन कर सकता हूं कि किसी .Net रिफ्लेक्टर के साथ पावरशेल के किसी भी संस्करण के लिए इसे कैसे एक्सेस किया जा सकता है (PowerShell Core 6.0 के लिए नीचे अपडेट देखें)।

सबसे पहले, यह पता लगाएं कि कौन सी लाइब्रेरी से Add-Typeआता है:

Get-Command -Name Add-Type | Select-Object -Property DLL

अपने परावर्तक के साथ परिणामी DLL खोलें। मैंने इसके लिए ILSpy का उपयोग किया है क्योंकि यह FLOSS है , लेकिन किसी भी C # रिफ्लेक्टर को काम करना चाहिए। उस लाइब्रेरी को खोलें, और अंदर देखें Microsoft.Powershell.Commands.Utility। के तहत Microsoft.Powershell.Commandsहोना चाहिए AddTypeCommand

उसके लिए कोड सूची में, एक निजी वर्ग है, InitializeStrongNameDictionary() । यह उन शब्दकोश को सूचीबद्ध करता है जो संक्षिप्त नामों को मजबूत नामों में मैप करता है। मैंने जिस लाइब्रेरी को देखा है, उसमें लगभग 750 प्रविष्टियाँ हैं।

अद्यतन: अब जब कि PowerShell Core 6.0 खुला स्रोत है। उस संस्करण के लिए, आप उपरोक्त चरणों को छोड़ सकते हैं और कोड को सीधे उनके GitHub रिपॉजिटरी में ऑनलाइन देख सकते हैं । मैं इस बात की गारंटी नहीं दे सकता कि कोड PowerShell के किसी अन्य संस्करण से मेल खाता है, हालाँकि।


3 अनुत्तरित प्रश्न: क्या होगा यदि मुझे एक विशिष्ट संस्करण की आवश्यकता नहीं है?
jpmc26

1
@ jpmc26 ठीक है, आप बस उपयोग कर सकते हैं Add-Typeया कर सकते हैं LoadWithPartialName(), लेकिन आपको यह जानने की आवश्यकता है कि पूर्व संस्करणों में 100% सुसंगत नहीं है और बाद वाला एक अप्रचलित तरीका है। दूसरे शब्दों में, .Net चाहता है कि आप उस लाइब्रेरी के संस्करण की परवाह करें जिसे आप लोड करते हैं।
बेकन बिट्स

@BaconBits jpmc26 के प्रश्न का पूर्ण उत्तर यह है कि आप PowerShell 5 या PowerShell 6 पर हैं, इस आधार पर, भरी हुई असेंबली भिन्न हो सकती है। JSON.NET को Azure PS फ़ंक्शन के साथ यह समस्या है।
जॉन ज़ब्रोस्की

@BaconBits यह PowerShell में वास्तव में शानदार गहरा गोता है। आपको एक किताब लिखनी चाहिए।
जॉन ज़ब्रोस्की

1
@KolobCanyon क्योंकि उस मामले में आपको आम तौर पर उपयोग करना चाहिए Add-Type -Path, जो कि उल्लेखित दूसरा कोड है, या Assembly.LoadFrom()जो आपके लिए निर्भरता का समाधान करता है (और, जहां तक ​​मैं बता सकता हूं, वह क्या Add-Type -Pathउपयोग करता है)। आपके द्वारा उपयोग किया जाने वाला एकमात्र समय Assembly.LoadFile()ऐसा है जब आपको कई विधानसभाओं को लोड करने की आवश्यकता होती है जिनकी एक ही पहचान होती है लेकिन अलग-अलग रास्ते। वह अजीब स्थिति है।
बेकन बिट्स

23

यदि आप PowerShell सत्र की अवधि के दौरान इसे लॉक किए बिना किसी असेंबली को लोड करना चाहते हैं , तो इसका उपयोग करें:

$bytes = [System.IO.File]::ReadAllBytes($storageAssemblyPath)
[System.Reflection.Assembly]::Load($bytes)

कहाँ पे $storageAssemblyPathआपकी विधानसभा की फ़ाइलपथ है

यह विशेष रूप से उपयोगी है यदि आपको अपने सत्र के भीतर रीसस को साफ करने की आवश्यकता है। उदाहरण के लिए परिनियोजन स्क्रिप्ट में।


1
👍 👍 👍 शानदार। क्योंकि Visual Studio में, Powershell को डीबग करते समय, PS सत्र निष्पादन के बाद (PowerShellToolsProcessHost के माध्यम से) घूमता है। यह दृष्टिकोण इसे ठीक करता है। धन्यवाद।
CJBS

15

PowerShell v1, v2 और v3 में असेंबलियों को लोड करने के तरीकों के कई उदाहरणों के साथ यहां कुछ ब्लॉग पोस्ट हैं।

तरीकों में शामिल हैं:

  • स्रोत फ़ाइल से गतिशील
  • एक विधानसभा से गतिशील
  • अन्य कोड प्रकारों का उपयोग करना, अर्थात F #

v1.0 कैसे PowerShell सत्र
v2.0 में .NET असेंबली लोड करने के लिए कैसे PowerShell स्क्रिप्ट में CSharp (C #) कोड का उपयोग कर 2.0
v3.0 Windows PowerShell में .NET फ्रेमवर्क असेंबलियों का उपयोग करना


10

आप पूरे * .d असेंबली को लोड कर सकते हैं

$Assembly = [System.Reflection.Assembly]::LoadFrom("C:\folder\file.dll");

3

किसी भी उत्तर ने मेरी मदद नहीं की, इसलिए मैं उस समाधान को पोस्ट कर रहा हूं जो मेरे लिए काम कर रहा है, मुझे केवल SQLPS मॉड्यूल को आयात करना है, मुझे इसका एहसास हुआ जब दुर्घटना से मैंने रिस्टोर-एसक्लाडेटाबेस कमांड चलाया और काम करना शुरू किया, जिसका अर्थ है असेंबली को किसी तरह उस मॉड्यूल में संदर्भित किया गया था।

बस दौडो:

Import-module SQLPS

नोट: ध्यान दें कि SQLPS पदावनत नहीं है के लिए धन्यवाद जेसन

इसके बजाय भागो:

Import-Module SqlServer

या

Install-Module SqlServer

2
इस दृष्टिकोण का उपयोग करने वाले किसी भी व्यक्ति के लिए, FYI करें जो sqlpsमॉड्यूल के पक्ष में पदावनत हैsqlserver
जेसन


2

आप उपयोग कर सकते हैं LoadWithPartialName। हालाँकि, जैसा कि उन्होंने कहा कि पदावनत किया गया है।

आप वास्तव में साथ जा सकते हैं Add-Type, और अन्य उत्तरों के अलावा, यदि आप .dll फ़ाइल का पूर्ण पथ निर्दिष्ट नहीं करना चाहते हैं, तो आप बस कर सकते हैं:

Add-Type -AssemblyName "Microsoft.SqlServer.Management.SMO"

मेरे लिए यह एक त्रुटि लौटा है, क्योंकि मेरे पास SQL ​​सर्वर स्थापित नहीं है (मुझे लगता है), हालांकि, इसी विचार के साथ मैं विंडोज फॉर्म असेंबली लोड करने में सक्षम था:

Add-Type -AssemblyName "System.Windows.Forms"

आप MSDN साइट पर किसी विशेष वर्ग से संबंधित सटीक असेंबली का नाम पता कर सकते हैं:

एक विशेष वर्ग से संबंधित विधानसभा नाम का पता लगाने का उदाहरण


2

सुनिश्चित करें कि आपके पास निम्न सुविधाएं हैं जो क्रम में स्थापित हैं

  1. Microsoft सिस्टम CLR प्रकार SQL सर्वर के लिए
  2. Microsoft SQL सर्वर साझा प्रबंधन ऑब्जेक्ट्स
  3. Microsoft Windows PowerShell एक्सटेंशन

इसके अलावा, आपको लोड करने की आवश्यकता हो सकती है

Add-Type -Path "C:\Program Files\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.Smo.dll"
Add-Type -Path "C:\Program Files\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.SqlWmiManagement.dll"

मैंने एक सप्ताह विधानसभा को लोड करने की कोशिश में बिताया और बयान से कोई आउटपुट नहीं देखा जो उन्हें लोड किया था, लेकिन जब मैंने इसका उपयोग करने की कोशिश की, तो मुझे त्रुटि मिली। जब मैंने इन तीन चीजों को स्थापित किया, तो यह काम किया। - धन्यवाद
अपराह्न

0

शीर्ष पर विधानसभा संदर्भ जोड़ें।

#Load the required assemblies SMO and SmoExtended.
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null

क्या आप इसका एक उदाहरण बना सकते हैं?
endo.anaconda

1
आपको इसे पॉवरशेल स्क्रिप्ट की शुरुआत में जोड़ने की जरूरत है। उदाहरण के लिए: डेटाबेस का बैकअप बनाएँ: [System.Reflection.Assembly] :: LoadWithPartialName ("Microsoft.SqlServer.SMO") | आउट-नल [System.Reflection.Assembly] :: LoadWithPartialName ("Microsoft.SqlServer.SmoExtended") | Out-Null $ SQLServer = Read-Host -rompt 'SQL Server नाम (वैकल्पिक)' IF ([string] :: IsNullOrWhitespace ($ SQLServer)) {$ SQLServer = "XXX";} $ SQLDBName = Read-Host -rompt ' SQL डेटाबेस नाम (वैकल्पिक) 'IF ([string] :: IsNullOrWhitespace ($ SQLDBName)) {$ SQLDBName = "XXX";} $ SQLLogin = Read-Host -Prompt' लॉगिन '
अमृता बसु
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.