2014-11-21 54 views
0

出於某種原因,我無法使用Get-Content cmdlet將此變量($ SelectedDrive)存儲在其中。變量不會在PowerShell中存儲數據

我已經創建了一個函數,如下所示:

#Allow user to select which drive to backup to and checks that the user hasn't canceled out of the Drive Selection GUI 
Function SelectDrive{ 
ShowUSBs | Out-File $locBackupFolder\RemovableStorage.txt 
Get-Content $locBackupFolder\RemovableStorage.txt | Out-GridView -OutputMode Single -Title "Choose USB Storage Device" | Out-File $locBackupFolder\Drive.txt -Encoding default 
$SelectedDrive = Get-Content $locBackupFolder\Drive.txt 
IF ($SelectedDrive -eq $null) { 
    WarningCancel 
    RemoveBackupDrive 
    Exit 
    } ELSE { 
    $BackupDrive = $SelectedDrive.Substring(0,2) 
    } 
} 

當我使用它貫穿F5按鈕Powershell的ISE運行腳本,然後未能進入數據。

我回去檢查一下,看不出任何問題,因爲它的工作原理是,如果我使用運行選擇一塊一塊地運行它。

整個腳本如下:

######### DEFINE FUNCTIONS ######### 
$locBackupFolder = "C:\Backup" 

#Check Backup Drive 
IF (!(Test-Path $locBackupFolder)) { 
    #C:\Backup does NOT exist 
    New-Item $locBackupFolder -ItemType Directory 
} 

#Inform user only D:\Username will be backed up 
function WarningDialog(
$MessageWarning = "!!!WARNING!!! 

YOU MAY LOSE DATA IF YOU DO NOT ADHERE TO THIS MESSAGE 

Only D:\$env:USERNAME will be backed up, please ensure any Data that is sitting in the root of D:\ is moved to D:\$env:USERNAME 

FYI: Your desktop data is safe and will be backed up, you need only worry about data in the root of D:\ or anything you have stored in 
C:\ Drive. 

FURTHER MORE Outlook will shutdown by itself through this process, please do not open it up again until everything is finished. 

If you have data to move, please click Cancel now, otherwise please press OK to continue the backup procedure. 

For any help, please see your IT Technicians, or call 
off-site.", 

$WindowTitleWarning = "Backup your data from your laptop", 
[System.Windows.Forms.MessageBoxButtons]$ButtonsWarning = [System.Windows.Forms.MessageBoxButtons]::OKCancel, 
[System.Windows.Forms.MessageBoxIcon]$IconWarning = [System.Windows.Forms.MessageBoxIcon]::Stop 
) 
{ 
    Add-Type -AssemblyName System.Windows.Forms 
    return [System.Windows.Forms.MessageBox]::Show($MessageWarning, $WindowTitleWarning, $ButtonsWarning, $IconWarning) 
} 

#Checks to see if logged on user has a D:\USERNAME directory and if not, informs them to see IT for a custom backup. 
Function TestUserDrive { 
    IF (!(Test-Path "D:\$env:USERNAME")){ 
     #D:\USERNAME does NOT exist 
    } 
} 

#Displays an instruction/how-to of how to move data from the root of D:\ to the users D:\USERNAME folder 
function WarningCancel(
$MessageCancel = "INSTRUCTIONS: 

You have chosen to cancel the backup script, if this is due to requiring data to be moved to inside your D:\$env:USERNAME folder, please do the following. 

1. Open My Computer 

2. Double click on Data (D:) to open your D:\ Drive 

3. Move or Copy anything from this directory that you wish to keep, into the directory called $env:USERNAME\My Documents 

4. Once this has been completed, re-run this script to commence the backup procedure again 

Easy as that! 

For any help, please see your IT Technicians, or call 
off-site", 
$WindowTitleCancel = "Backup your data from your laptop", 
[System.Windows.Forms.MessageBoxButtons]$ButtonsCancel = [System.Windows.Forms.MessageBoxButtons]::OK, 
[System.Windows.Forms.MessageBoxIcon]$IconCancel = [System.Windows.Forms.MessageBoxIcon]::Information 
) 
{ 
    Add-Type -AssemblyName System.Windows.Forms 
    return [System.Windows.Forms.MessageBox]::Show($MessageCancel, $WindowTitleCancel, $ButtonsCancel, $IconCancel) 
} 

#Informs the user to select the device they would like to backup to when the selection box is displayed 
function SelectDevicePrompt(
$MessageSelect = "On the next screen please specify the device you would like to backup your data to. 

The devices you currently have plugged in will show, please select your chosen device, and then click the OK button at the bottom right of the window.", 

$WindowTitleSelect = "Backup your data from your laptop", 
[System.Windows.Forms.MessageBoxButtons]$ButtonsSelect = [System.Windows.Forms.MessageBoxButtons]::OK, 
[System.Windows.Forms.MessageBoxIcon]$IconSelect = [System.Windows.Forms.MessageBoxIcon]::Hand 
) 
{ 
    Add-Type -AssemblyName System.Windows.Forms 
    return [System.Windows.Forms.MessageBox]::Show($MessageSelect, $WindowTitleSelect, $ButtonsSelect, $IconSelect) 
} 

#Displays a list of all removable storage devices volume names and their allocated drive letter 
Function ShowUSBs{ 
$USBInfo = gwmi win32_diskdrive | ?{$_.interfacetype -eq "USB"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} 
$USBInfo | Format-Table ` 
    @{Expression={$_.DeviceID};Label="Drive Letter";Width=25}, ` 
    @{Expression={$_.VolumeName};Label="USB Name";Width=20} 
} 

#Allow user to select which drive to backup to and checks that the user hasn't canceled out of the Drive Selection GUI 
Function SelectDrive{ 
ShowUSBs | Out-File $locBackupFolder\RemovableStorage.txt 
Get-Content $locBackupFolder\RemovableStorage.txt | Out-GridView -OutputMode Single -Title "Choose USB Storage Device" | Out-File $locBackupFolder\Drive.txt -Encoding default 
$SelectedDrive = Get-Content $locBackupFolder\Drive.txt 
IF ($SelectedDrive -eq $null) { 
    WarningCancel 
    RemoveBackupDrive 
    Exit 
    } ELSE { 
    $BackupDrive = $SelectedDrive.Substring(0,2) 
    } 
} 
$BackupDrive 

#Imports list of active processes and looks for outlook process then kills it if found 
function KillOutlook{ 
$processactive = Get-Process 
IF($processactive.ProcessName -contains "Outlook") { 
    Stop-Process -Name Outlook 
    Start-Sleep 1 
    $OLcheckagain = Get-Process 
    IF($OLcheckagain.Processname -contains "Outlook") { 
     Write-Host "Outlook failed to close" 
     } 
    } Else { 
    Write-Host "Outlook is closed" 
    } 
} 

#Find the pst files attached to outlook and output the values to C:\Backup\PST.txt 
function FindPSTs{ 
$outlook = New-Object -comObject Outlook.Application 
$pstloc = $outlook.Session.Stores | where { ($_.FilePath -like '*.PST') } 
$pstloc.FilePath | out-file -FilePath "$locBackupFolder\PST.txt" -Encoding Default 
} 

#Removes C:\Backup Directory 
Function RemoveBackupDrive { 
    IF (Test-Path $locBackupFolder){ 
    Remove-Item $locBackupFolder -Force -Recurse 
    } 
} 

#Copy data from D:\USERNAME to BackupDrive 
Function CopyData { 
    IF (!(Test-Path $BackupDrive)) { 
    robocopy D:\$env:USERNAME $BackupDrive /MIR /COPYALL /r:03 /w:5 /MT:9 
    } ELSE { 
    robocopy D:\$env:USERNAME $BackupDrive/
    } 
} 

#Copy PST files explicitly to BackupDrive\AppData\Roaming\Email 
Function CopyPST { 
    KillOutlook 
    Start-Sleep 1 
    IF (!(Test-Path $BackupDrive\AppData\Roaming\Email)) { 
    New-Item $BackupDrive\AppData\Roaming\Email -ItemType Directory 
    } 
    Get-Content $locBackupFolder\PST.txt | ForEach-Object { 
     IF (Test-Path $_){ 
     Copy-Item $_ "$BackupDrive\AppData\Roaming\Email" 
     } 
    } 
} 


######### START SCRIPT ######### 

#Display warning to inform user that only D:\USERNAME will be backed up 
$WarningAccept = WarningDialog 

#If cancel is selected from WarningDialog, then display WarningCancel message pop-up giving instructions to backup data from D:\ to D:\USERNAME 
IF ($WarningAccept -eq "Cancel") { 
WarningCancel 
RemoveBackupDrive 
Exit 
} 

#Prompts user to select Device to backup to 
SelectDevicePrompt 

#Shows the selection page for the user to select the device 
SelectDrive 

#Find the pst files attached to outlook and output to C:\Backup\PST.txt 
FindPSTs 

#Inform user where their data will be backed up to 
Write-Host "Your data will be backed up to $BackupDrive" 

#If Outlook is found, stop its process, otherwise continue 
KillOutlook 

#Running backup of everything in D:\ drive using robocopy 
#If this is the first time copying all data /MIR will be used, otherwise if the directory DRIVE:\USERNAME\Backup exists 
#robocopy will not /MIR and will only update newly added data. 
CopyData 

#Copy PST files specifically 
#CopyPST 

如果我能提供任何進一步的幫助,請讓我知道。

+0

您是否在'$ locBackupFolder \ Drive.txt'手動檢查了文件內容?它是空的還是有數據的? – 2014-11-21 06:06:05

+0

Hi @VikasGupta我檢查了Drive.txt文件的內容,並且它裏面有數據。 – Random206 2014-11-21 09:12:11

+0

請解釋「無法輸入數據」的含義。進入哪裏? rading文件後'$ SelectedDrive'的內容是什麼,以及哪個操作完全失敗? – 2014-11-21 10:09:05

回答

1

我認爲你的問題很簡單,就是SelectDrive函數不返回任何東西。 $backupDrive是本地函數,所以你不能從函數外部引用它。

同樣將所有內容轉換爲文本都會引入其​​他錯誤,例如您可以從網格視圖中選擇任何線條,包括標題和空白行頂部和底部。一些更好的代碼可能是:

Function GetUSBs{ 
    $USBInfo = gwmi win32_diskdrive | 
     ?{$_.interfacetype -eq "USB"} | 
     %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} | 
     %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} 
    Write-Output $USBInfo | select @{n="Drive Letter";e={$_.DeviceID}},@{n="USB Name";e={$_.VolumeName}} 
} 

Function SelectDrive{ 
    $usbs = GetUSBs 
    $usbs | Format-Table -AutoSize | Out-File $locBackupFolder\RemovableStorage.txt 

    $selectedDrive = $usbs | Out-GridView -OutputMode Single -Title "Choose USB Storage Device" 
    $selectedDrive | Out-File $locBackupFolder\Drive.txt -Encoding default 

    if ($SelectedDrive -eq $null) { 
     WarningCancel 
     RemoveBackupDrive 
     exit 
    } else { 
    write-output $selectedDrive.'Drive Letter'.Substring(0,2) 
    } 
} 
$backupDrive = SelectDrive 

這個版本還寫到你的兩個文件,但它不讀取任何一方,而是將其保持的對象內部。這意味着您在網格視圖中獲得了更好的顯示效果,因爲使用了網格自己的列標題,並且不會獲得您不需要的任何可選行。

+0

你是一個friggen天才!非常感謝你,你不僅幫助我,還使腳本更好! KUDOS! – Random206 2014-11-24 01:14:51

0

有很多在你的腳本的時候,我通過它調試自己,發現這些線路出現了問題

ShowUSBs | Out-File $locBackupFolder\RemovableStorage.txt 
Get-Content $locBackupFolder\RemovableStorage.txt | Out-GridView -OutputMode Single -Title "Choose USB Storage Device" | Out-File $locBackupFolder\Drive.txt -Encoding default 
$SelectedDrive = Get-Content "$locBackupFolder\Drive.txt" 

您需要刪除的代碼塊:

Out-File $locBackupFolder\Drive.txt -Encoding default 

它正在創建一個新的空白Drive.txt文件,之後,在該空文件上調用Get-Content

因此,它正在獲取空白文件的內容,這將始終導致$SelectedDrive變量被設置爲空。

後此塊已被刪除,$SelectedDrive變量設置爲文件的內容如預期

+0

謝謝@ShaneC然而,當用戶點擊他們想要選擇備份到的驅動器時,然後單擊確定,Out-GridView中選定的數據回寫到txt文件在舊的Powershell版本中,out-gridview只顯示數據,但是在新的Powershell版本中它允許你選擇並傳回數據,你使用的是Windows 8.1嗎?我是? – Random206 2014-11-21 09:40:29

+0

我正在使用8.1,每次我運行了你的代碼,驅動文件被一個空白文件覆蓋了,你的代碼假定$ locBackupFolder存在並且有文件,即使這個目錄是在腳本的前面創建的(如果它不存在)。關於可能不存在的文件的內容 – ShaneC 2014-11-21 12:26:56

0

你似乎想到這個結構將無法正常工作我已經添加內容到我的Drive.txt文件:

Get-Content file | Out-GridView | Out-File otherfile 

Out-GridView不會將數據傳回管道進行進一步處理。如果您需要在這兩個網格視圖你需要Out-GridView前使用Tee-Object cmdlet的一個文件中的數據:

Get-Content file | Tee-Object otherfile | Out-GridView 

你的情況:

Get-Content "$locBackupFolder\RemovableStorage.txt" | 
    Tee-Object "$locBackupFolder\Drive.txt" | 
    Out-GridView -OutputMode Single -Title 'Choose USB Storage Device' 

如果你希望用戶選擇一個特定的項目,Out-GridView將不會工作,因爲它只爲輸出(因此動詞Out)。你需要一個form with a list box以允許用戶選擇一個項目:

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 

$frm = New-Object Windows.Forms.Form 

$btn = New-Object Windows.Forms.Button 
$btn.Location = New-Object Drawing.Size(10,220) 
$btn.Size = New-Object Drawing.Size(75,23) 
$btn.Text = "OK" 
$btn.Add_Click({$frm.Close()}) 
$frm.Controls.Add($btn) 

$list = New-Object Windows.Forms.ListBox 
$list.Location = New-Object Drawing.Size(10,10) 
$list.Size = New-Object Drawing.Size(260,40) 
$list.Height = 200 
Get-Content "$locBackupFolder\RemovableStorage.txt" | % { 
    $list.Items.Add($_) 
} | Out-Null 
$frm.Controls.Add($list) 

$frm.Add_Shown({$frm.Activate()}) 
[void]$frm.ShowDialog() 

$SelectedDrive = $list.SelectedItem 
+0

Hi @AnsgarWiechers在Powershell的最新版本中,Out-GridView允許您選擇並輸出選擇。我有Out- GridView工作正常,並且它輸出到$ locBackupFolder \ drive.txt,它只是下一部分(Get-Content),它不適合我。 – Random206 2014-11-21 09:45:41

+0

@ Random206定義「不適合我」。手術的實際結果是什麼?這與預期的結果有什麼不同? – 2014-11-21 10:10:11

+0

定義「不適用於我」...變量$ SelectedDrive爲空時,它應該包含$ locbackupfolder \ Drive.txt中的字符串,一旦將其加載到變量中,則$ BackupDrive將從第一個2字母字符串,並將另一個字符串連接到它的末尾。但是它不能這樣做,因爲$ SelectedDrive變量是空白的。 – Random206 2014-11-21 10:19:43