Сценарий PowerShell не удается в первый раз, но работает во второй раз - PullRequest
5 голосов
/ 27 мая 2011

Я нашел сценарий PowerShell , который может изменить обои рабочего стола моего ПК с Windows 7 файла изображения, путь которого указан в качестве параметра.В результате я хочу, чтобы этот скрипт вызывался командным файлом при запуске.

[CmdletBinding()]
Param(
   [Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
   [Alias("FullName")]
   [string]
   $Path
,
   [Parameter(Position=1, Mandatory=$false)]
   $Style = "NoChange"
)

BEGIN {
try {
   $WP = [Wallpaper.Setter]
} catch {
   $WP = add-type @"
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace Wallpaper
{
public enum Style : int
{
     Tile, Center, Stretch, NoChange
}

public class Setter {
  public const int SetDesktopWallpaper = 20;
  public const int UpdateIniFile = 0x01;
  public const int SendWinIniChange = 0x02;

  [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  private static extern int SystemParametersInfo (int uAction, int uParam, string lpvParam, int fuWinIni);

  public static void SetWallpaper ( string path, Wallpaper.Style style ) {
     SystemParametersInfo( SetDesktopWallpaper, 0, path, UpdateIniFile | SendWinIniChange );

     RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);
     switch( style )
     {
        case Style.Stretch :
           key.SetValue(@"WallpaperStyle", "2") ; 
           key.SetValue(@"TileWallpaper", "0") ;
           break;
        case Style.Center :
           key.SetValue(@"WallpaperStyle", "1") ; 
           key.SetValue(@"TileWallpaper", "0") ; 
           break;
        case Style.Tile :
           key.SetValue(@"WallpaperStyle", "1") ; 
           key.SetValue(@"TileWallpaper", "1") ;
           break;
        case Style.NoChange :
           break;
     }
     key.Close();
    }
   }
}
"@ -Passthru
}
}
PROCESS {
   Write-Verbose "Setting Wallpaper ($Style) to $(Convert-Path $Path)"
   $WP::SetWallpaper( (Convert-Path $Path), $Style )
}

Я вызываю этот скрипт с помощью команды:

C:\ scripts \ Set-Wallpaper.ps1 C: \ Users \ myProfile \ Pictures \ MyWallpaper.jpg

Я совершенно новичок в мире сценариев PowerShell, и проблема в том, чтокогда я выполняю скрипт из PowerShell, он всегда в первый раз завершается с ошибкой:

C: \ scripts \ Set-Wallpaper.ps1: Невозможно привести объект типа 'System.Object [] 'для ввода' System.Type '.

В строке: 1 символ: 29

  • C: \ scripts \ Set-Wallpaper.ps1 <<<< C: \ Users\ mbaleato \ Pictures \ MyWallpaper.jpg <ul>
  • CategoryInfo: Не указано: (:) [Set-Wallpaper.ps1], InvalidCastException
  • FullyQualifiedErrorId: System.InvalidCastException, Set-Wallpaper.ps1

Но когда я вызываю скрипт с точно такой же командой и параметром во второй раз, этоks.

Это сбой в первый раз, который вызывает сбой моего командного файла.

У всех, кто более опытен, есть несколько советов относительно того, почему он терпит неудачу в первый раз, но работает во второй раз?Какие-нибудь предложения относительно того, как я могу заставить это работать в первый раз?

Ответы [ 3 ]

7 голосов
/ 27 мая 2011

Посмотрите на строку, которая начинается с $WP = add-type @". Это проблема. Вы создаете два типа:

$wp

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Style                                    System.Enum
True     False    Setter                                   System.Object

Попробуйте позвонить Add-Type без -Passthru и после этого назначить $wp

Add-Type -typedef @"
...
"@
$WP = [Wallpaper.Setter]
5 голосов
/ 27 мая 2011

Я полагаю, это потому, что passthru превращает $ WP в массив - вы можете попробовать это попробовать вместо этого:

try {
   $WP = [Wallpaper.Setter]
} catch {
   add-type @"
....
"@
    $WP = [Wallpaper.Setter]
}

Это можно увидеть, запустив его построчно и проверив tyoe:

PS D:\bin\OpenSSL-Win32\bin> $WP

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Style                                    System.Enum
True     False    Setter                                   System.Object

PS D:\bin\OpenSSL-Win32\bin> $WP.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array


PS D:\bin\OpenSSL-Win32\bin> $WP = [Wallpaper.Setter]
PS D:\bin\OpenSSL-Win32\bin> $WP.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
False    True     RuntimeType                              System.Type

Второй раз тип уже существует, поэтому% WP загружен правильно.

0 голосов
/ 27 мая 2011

Внутри скрипт Powershell:

PS c:\> & 'C:\scripts\Set-Wallpaper.ps1' C:\Users\myProfile\Pictures\MyWallpaper.jpg

Из cmd.exe

C:\> PowerShell -command "& 'C:\scripts\Set-Wallpaper.ps1' C:\Users\myProfile\Pictures\MyWallpaper.jpg"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...