我如何在PowerShell中创建一个Outlook规则,使用与C#完美相同的代码将电子邮件移动到一个文件夹而不出错?

我如何在PowerShell中创建一个Outlook规则,使用与C#完美相同的代码将电子邮件移动到一个文件夹而不出错?,c#,powershell,email,outlook,office-interop,C#,Powershell,Email,Outlook,Office Interop,我正在尝试编写PowerShell代码以创建Outlook规则来移动电子邮件,但它不起作用 注意我没有访问服务器的权限,因此像New-InboxRule这样的*-InboxRulecmdlet不可用 PowerShell和Outlook之间的COM互操作有些不可靠,因为它在C#中工作得很好,但PowerShell中的相同代码却不工作 下面是C代码,它可以完美地工作: 现在,这里是相同的(语言语法除外)PowerShell代码: try { $outlook = [Runtime.Inte

我正在尝试编写PowerShell代码以创建Outlook规则来移动电子邮件,但它不起作用

注意我没有访问服务器的权限,因此像
New-InboxRule
这样的
*-InboxRule
cmdlet不可用

PowerShell和Outlook之间的COM互操作有些不可靠,因为它在C#中工作得很好,但PowerShell中的相同代码却不工作

下面是C代码,它可以完美地工作:

现在,这里是相同的(语言语法除外)PowerShell代码:

try
{
    $outlook = [Runtime.InteropServices.Marshal]::GetActiveObject("Outlook.Application");
}
catch
{
}

if ($outlook -eq $null)
{
    $outlook = New-Object -ComObject Outlook.Application
}

$inbox = $outlook.Application.Session.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox);
$oMoveTarget = $inbox.Folders["MoveTarget"];

# debugging
[Console]::WriteLine($inbox.FolderPath.ToString());
[Console]::WriteLine($oMoveTarget.FolderPath.ToString());

$rules = $outlook.Session.DefaultStore.GetRules();
[Console]::WriteLine([string]::Format("There are {0} rules", $rules.Count));

$name = [string]::Format("Rule {0}", [DateTime]::Now.ToString("yyyyMMdd_HHmmss"));
$rule = $rules.Create($name, [Microsoft.Office.Interop.Outlook.OlRuleType]::olRuleReceive);

# conditions
$rule.Conditions.From.Recipients.Add("John Smith");
$rule.Conditions.From.Recipients.ResolveAll();
$rule.Conditions.From.Enabled = $true;

# actions
$rule.Actions.MoveToFolder.Folder = $oMoveTarget;
$rule.Actions.MoveToFolder.Enabled = $true;
$rules.Save($true);
C#代码成功时,PS代码失败,原因是:

One or more rules cannot be saved because of invalid actions or conditions.
At line:1 char:1
+ $rules.Save($true);
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], COMException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
 
经进一步调查,这基本上是由这条线路引起的,它实际上没有做任何事情:

$rule.Actions.MoveToFolder.Folder = $oMoveTarget;
当我运行C#等价物时,如果我立即转过身来查看该属性,它就会被设置。但是,在PowerShell中,它不会抛出错误或任何东西。。。它只是默默地什么也不做

我怎样才能让它工作?请帮忙

您可以在powershell中运行C#代码。是否需要在powershell中重写它

$code = @'
using System;

namespace Outlook
{
    public class Outlook
    {
        public static void Main(){
            Microsoft.Office.Interop.Outlook.Application outlook = null;

            try
            {
                outlook = (Microsoft.Office.Interop.Outlook.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Outlook.Application");
            }
            catch
            {
            }

            if (outlook == null)
            {
                outlook = new Microsoft.Office.Interop.Outlook.Application();
            }

            var inbox = outlook.Application.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
            var oMoveTarget = inbox.Folders["TargetFolder"];

            // debugging
            Console.WriteLine(inbox.FolderPath.ToString());
            Console.WriteLine(oMoveTarget.FolderPath.ToString());

            var rules = outlook.Session.DefaultStore.GetRules();
            Console.WriteLine(string.Format("There are {0} rules", rules.Count));

            var name = string.Format("Rule {0}", DateTime.Now.ToString("yyyyMMdd_HHmmss"));
            var rule = rules.Create(name, Microsoft.Office.Interop.Outlook.OlRuleType.olRuleReceive);

            // conditions
            rule.Conditions.From.Recipients.Add("John Smith");
            rule.Conditions.From.Recipients.ResolveAll();
            rule.Conditions.From.Enabled = true;

            // actions
            rule.Actions.MoveToFolder.Folder = oMoveTarget;
            rule.Actions.MoveToFolder.Enabled = true;
            rules.Save(true);
        }
    }
}
'@

$assemblies = ("Microsoft.Office.Interop.Outlook")

Add-Type -ReferencedAssemblies $assemblies  -TypeDefinition $code -Language CSharp

[Outlook.Outlook]::Main()
您可以通过以下方式执行此操作:

# actions
$action = $rule.Actions.MoveToFolder
$action.Enabled = $true

[Microsoft.Office.Interop.Outlook.MoveOrCopyRuleAction].InvokeMember("Folder",[Reflection.BindingFlags]::SetProperty, $null, $action, $oMoveTarget) 


那真的没用。我已经知道如何在C#中实现它,我知道如何在PS中嵌入C#。我想知道如何直接实现它,这样我就有了完整的逐行灵活性。天哪,这是可行的!有人怎么会知道这件事?!?!这只是了解PS如何处理COM的一个技巧。这不是很明显,但是在PS中使用COM的许多其他例子中,这种东西也很有用。你怎么知道的?呵呵,请给我们指一个博客、书或视频。想要学习Nabraham:获取PS源代码,构建并调试它。:-)
# actions
$action = $rule.Actions.MoveToFolder
$action.Enabled = $true

[Microsoft.Office.Interop.Outlook.MoveOrCopyRuleAction].InvokeMember("Folder",[Reflection.BindingFlags]::SetProperty, $null, $action, $oMoveTarget)