بوويرشيل معالجة الأوامر (يمر في المتغيرات)
-
03-07-2019 - |
سؤال
وأنا إنشاء برنامج نصي PowerShell لنشر بعض رمز وجزء من هذه العملية هو الدعوة إلى أداة ضغط سطر الأوامر تسمى RAR.EXE إلى احتياطية بعض المجلدات.
وأنا محاولة لبناء حيوي من المعلمات ومن ثم إجراء مكالمة بوويرشيل الأمر مع المتغيرات ولكن أنا على التوالي في ورطة. انها لا تعمل ...
وتشغيل البرنامج النصي التالي، ويجب أن نرى ما أتحدث عنه. المعلمات يتم تمريرها في كما يتم المهترئ متغير. إذا مررت الأمر بالكامل + المعلمات في أحصل سيئة السمعة "لم يتم التعرف على أمر cmdlet ..." رسالة.
وشكرا على اي مساعدة!
echo "this should succeed"
& cmd /c echo foo
echo "why does this echo out an additional double quote?"
$param = "/c echo foo"
& cmd "$param"
echo "this does the same"
$param = "/c echo foo"
& cmd $param
echo "escaping the slash doesn't work either..."
$param = "`/c echo foo"
& cmd $param
echo "this fails, but why?"
$cmd = "cmd /c echo foo"
&$cmd
المحلول
والمشغل الدعوة "و" لا لزوم لها في هذه الحالة. فهو يستخدم لاستدعاء أمر في نطاق جديد. وعادة ما تستخدم هذه استدعاء الأمر المحدد من قبل سلسلة أو scriptblock. كما أن لديها مصلحة الفريق الذي أية متغيرات خلقت في القول السيناريو بوويرشيل والتخلص منها بعد انتهاء القيادة ونطاق يذهب بعيدا.
ولكن منذ كمد هو EXE ينفذ في عملية مختلفة تماما. FWIW، تحصل إخراج مشابه مباشرة من CMD.EXE:
> cmd "/c echo foo"
foo"
وهكذا الاقتباس إضافية على النهاية هو قضية CMD.EXE. وعادة ما تحتاج إلى الحفاظ على الأمر منفصلة عن المعلمات عندما بوويرشيل تقوم به إعراب استدعاء الأمر منها مثلا.
45> & { $foo = "foo" }
46> $foo # Note that $foo wasn't found - it went away with the scope
47> . { $foo = "foo" } # dotting executes in the current scope
48> $foo
foo
والاستثناء الملحوظ هنا هو أن استدعاء-التعبير يتصرف وكأنه "تقييم هذه السلسلة" وظيفة. استخدام مع الرعاية، <م> خاصة م> إذا كان المستخدم يوفر السلسلة. يومك يمكن أن تمتص إذا قدموا "ري C: \ -r".
في هذه الحالة، كما فعل آخرون قد اقترح أود أن سحب / ج من سلسلة المعلمة سلسلة $ وتحديد ذلك منها مثلا:
cmd /c $param
وأو استخدام استدعاء-التعبير ولكن استخدام بحذر. BTW عندما تحاول تصحيح الأخطاء وحل المشكلات مع إرسال الحجج لEXE من بوويرشيل، وتحقق من فائدة echoargs في بوويرشيل ملحقات المجتمع ( HTTP: / /pscx.codeplex.com ). وهو مفيد جدا:
49> $param = "/c echo foo"
50> echoargs $param
Arg 0 is </c echo foo>
وهذا يدل على أن CMD.EXE يتلقى "/ ج صدى فو" باعتباره <م> واحدة م> حجة. "/ ج" يجب أن يكون حجة منفصلة عن "صدى فو" (الأمر إلى تنفيذ).
نصائح أخرى
ولقد كان لي مشاكل مع واستدعاء عامل في الماضي عند محاولة استدعاء الأوامر نوع القابلة للتنفيذ وكأنك تحاول. لست متأكدا أفهم لماذا. استدعاء-التعبير ومع ذلك، يبدو دائما للعمل في هذا السياق:
PS C:\> $cmd = "cmd /c echo foo"
PS C:\> Invoke-expression $cmd
foo
وكانت ثمة طريقة أخرى وجدت أن تفعل هذا لخلق مجموعة من الحجج لسطر الأوامر واستخدام ذلك مع apersand واستدعاء المشغل. شيء من هذا القبيل:
$exe = "cmd";
[Array]$params = "/c", "echo", "foo";
& $exe $params;
وسارت الامور بشكل جيد بالنسبة لي.
ولقد وجدت في الأصل هذه التقنية هنا: http://techstumbler.blogspot.com/2009/12 /windows-commands-with-arguments-in.html
واخر مثال لديك إذا فشلت ل"و" يعامل السلسلة ك وسيطة واحدة، لذلك تبحث عن برنامج يسمى "كمد / ج صدى foo.exe". :)
وهذا يعمل:
& $cmd $params
وأما بالنسبة لمسألة الاقتباس مزدوجة، فإنه لا يبدو أن كمد لا يحب علامات الاقتباس حول الحجج التي يضع بوويرشيل. يحصل هذا:
cmd "/c echo foo"
وهكذا أعتقد أنه يعامل كل شيء بعد / ج كأمر المحدد، وذلك كما يلي:
echo foo"
وبعض البرامج سطر الأوامر والتوزيع غير تقليدي من سطر الأوامر (وهذا هو السبب يأخذ بوويرشيل خلال هذا العمل للمهام وأوامر cmdlets). في حالة كمد، أود أن أقترح هذا:
$param = "echo foo"
& cmd /c $param
وانها قطعة أثرية من استخدام كمد / ج، على ما أعتقد. تشغيل
$param = "echo foo"
cmd /c $param
ويعمل بشكل جيد. لم يكن لديك المثال رمز حقيقي، فمن الصعب بعض الشيء لمشكلة تبادل لاطلاق النار.
وسائط مختلفة عندما كانت مضمنة في سلسلة:
PS D:\> echo "1 2 3"
1 2 3
PS D:\> echo 1 2 3
1
2
3
وتحدث نفس النتائج عند استخدام متغير لوسائط:
PS D:\> $param = "1 2 3"
PS D:\> echo $param
1 2 3
والحل هو استخدام صفيف:
PS D:\> $param = @(1,2,3)
PS D:\> echo $param
1
2
3