URL错误中的Powershell webclient尾随点

时间:2013-12-29 09:36:12

标签: .net powershell webclient

所以,我有一个下载文件的Powershell脚本,例如

$mech = new-object System.Net.WebClient
$mech.DownloadFile('http://www.example.com/folder./index.html', 'out.html')
                      Note the trailing dot here ^

哪个不起作用(给出404),查看发送的实际请求,结果发现尾随点被取出,这似乎源于此错误:https://connect.microsoft.com/VisualStudio/feedback/details/386695/

这似乎在.Net的某些版本中得到修复,但Powershell不使用这些版本(我在Win7中使用PS2.0,它使用.Net 2.0.50727.5472,也在PS3中尝试过.0使用的是.Net 4.0.30319.17929,两者都没有打补丁.Net 4.5。安装了一些东西)

所以,这可能是一个简单的问题,但是,上面的链接中列出了一个解决方法,我将如何在Powershell中应用它?

或者,如何让Powershell使用.Net的修补版本(哪些版本已修补?)

我宁愿不使用像wget这样的外部程序,否则我不能在Powershell中写这个,但是如果必须的话,它需要在url中支持UTF8

此外,服务器对此不满意。替换为%2e

2 个答案:

答案 0 :(得分:0)

如何采用低级方法并将WinInetP/Invoke一起使用? P / Invoke的介绍在MSDN。使用.Net类的工作要多得多。

另一种替代方法可能是使用第三方工具包,例如cURL。 Libcurl有一个.Net包装器,因此在Powershell中使用它应该比P / Invoke方式更容易。

答案 1 :(得分:0)

好吧,以防万一其他人需要解决方案,这是一个虽然我不能确切地说这是一个优雅的解决方案,但它仍然是一个。事实证明,您可以将C#直接推送到PS版本的PS> = 3.0

$source = @"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Net;


public class FixedWebClient
{
    public static System.Net.WebClient NewWebClient()
    {
        MethodInfo getSyntax = typeof(UriParser).GetMethod("GetSyntax", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
        FieldInfo flagsField = typeof(UriParser).GetField("m_Flags", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        if (getSyntax != null && flagsField != null)
        {
            foreach (string scheme in new[] { "http", "https" })
            {
                UriParser parser = (UriParser)getSyntax.Invoke(null, new object[] { scheme });
                if (parser != null)
                {
                    int flagsValue = (int)flagsField.GetValue(parser);
                    // Clear the CanonicalizeAsFilePath attribute
                    if ((flagsValue & 0x1000000) != 0)
                        flagsField.SetValue(parser, flagsValue & ~0x1000000);
                }
            }
        }
        return new System.Net.WebClient();
    }
}
"@

#Remove-TypeData 'FixedWebClient'
Add-Type -TypeDefinition $source
$mech = [FixedWebClient]::NewWebClient()
$mech.DownloadFile('http://www.example.com/folder./index.html', 'out.html')

我不确定效果的范围是使用这样的方法,所以我在其中创建WebClient对象以防万一,如果有更多PS / .Net经验的人可以澄清,那就太好了(这是我的第一个PS脚本,我使用Perl,但看到我更像是一个Windows家伙,我想我也可以学习一些PS。)

如果有人将其翻译成纯PS也会很好,因为看看它是如何工作会很有趣......