Data type conversion issues in Powershell
I'm writing a Powershell script that will extract a set of data files from a ZIP file and will then attach them to a server. I've written a function that takes care of the unzip and since I need to grab all of the files so that I know what I'm attaching I return that from the function:
function Unzip-Files
{
param([string]$zip_path, [string]$zip_filename, [string]$target_path, [string]$filename_pattern)
# Append a \ if the path doesn't already end with one
if (!$zip_path.EndsWith("\")) {$zip_path = $zip_path + "\"}
if (!$target_path.EndsWith("\")) {$target_path = $target_path + "\"}
# We'll need a string collection to return the files that were extracted
$extracted_file_names = New-Object System.Collections.Specialized.StringCollection
# We'll need a Shell Application for some file movement
$shell_application = New-Object -com shell.Application
# Get a handle for the target folder
$target_folder = $shell_application.NameSpace($target_path)
$zip_full_path = $zip_path + $zip_filename
if (Test-Path($zip_full_path))
{
$target_folder = $shell_application.NameSpace($target_path)
$zip_folder = $shell_application.NameSpace($zip_full_path)
foreach ($zipped_file in $zip_folder.Items() | Where {$_.Name -like $filename_pattern})
{
$extracted_file_names.Add($zipped_file.Name) | Out-Null
$target_folder.CopyHere($zipped_file, 16)
}
}
$extracted_file_names
}
I then call another function to actually attach the database (I've removed some code that checks for existence of the database, but that shouldn't affect things here):
function Attach-Database
{
param([object]$server, [string]$database_name, [object]$datafile_names)
$database = $server.Databases[$database_name]
$server.AttachDatabase($database_name, $datafile_names)
$database = $server.Databases[$database_name]
Return $database
}
I keep getting an error though, "Cannot convert argument "1", with value: "System.Object[]", for "AttachDatabase" to type "System.Collections.Specialized.StringCollection"".
I've tried declaring the data types explicitly at various points, but that just changes the location where I get the error (or one similar to it). I've also changed the parameter declaration to use the string collection instead of object开发者_开发知识库 with no luck.
I'm starting with a string collection and ultimately want to consume a string collection. I just don't seem to be able to get Powershell to stop trying to convert it to a generic Object at some point.
Any suggestions?
Thanks!
It looks like you should return the names using the comma operator:
...
, $extracted_file_names
}
to avoid "unrolling" the collection to its items and to preserve the original collection object.
There were several questions like this, here is just a couple:
Strange behavior in PowerShell function returning DataSet/DataTable
Loading a serialized DataTable in PowerShell - Gives back array of DataRows not a DataTable
UPDATE:
This similar code works:
Add-Type @'
using System;
using System.Collections.Specialized;
public static class TestClass
{
public static string TestMethod(StringCollection data)
{
string result = "";
foreach (string s in data)
result += s;
return result;
}
}
'@
function Unzip-Files
{
$extracted_file_names = New-Object System.Collections.Specialized.StringCollection
foreach ($zipped_file in 'xxx', 'yyy', 'zzz')
{
$extracted_file_names.Add($zipped_file) | Out-Null
}
, $extracted_file_names
}
function Attach-Database
{
param([object]$datafile_names)
# write the result
Write-Host ([TestClass]::TestMethod($datafile_names))
}
# get the collection
$names = Unzip-Files
# write its type
Write-Host $names.GetType()
# pass it in the function
Attach-Database $names
As expected, its output is:
System.Collections.Specialized.StringCollection
xxxyyyzzz
If I remove the suggested comma, then we get:
System.Object[]
Cannot convert argument "0", with value: "System.Object[]",
for "TestMethod" to type "System.Collections.Specialized.StringCollection"...
The symptoms look the same, so the solution presumably should work, too, if there are no other unwanted conversions/unrolling in the omitted code between Unzip-Files
and Attach-Database
calls.
精彩评论