C# AppDomain.CurrentDomain.BaseDirectory更改为错误目录

C# AppDomain.CurrentDomain.BaseDirectory更改为错误目录,c#,pscmdlet,C#,Pscmdlet,我使用Cmdlet命令创建了dll(请参阅Get\u DemoNames.cs)。通过这个cmdlet我调用了一个方法UpdateXml(),到目前为止一切都正常。但是UpdateXml()也会创建不存在的文件。在类文件中调用UpdateXml()时,如下所示: var parser = new Parser(); parser.UpdateXml(); PM> Import-Module C:\projects\EF.XML\EF.XML.dll PM> DemoNames 我

我使用
Cmdlet
命令创建了
dll
(请参阅Get\u DemoNames.cs)。通过这个
cmdlet
我调用了一个方法
UpdateXml()
,到目前为止一切都正常。但是
UpdateXml()
也会创建不存在的文件。在类文件中调用
UpdateXml()
时,如下所示:

var parser = new Parser();
parser.UpdateXml();
PM> Import-Module C:\projects\EF.XML\EF.XML.dll
PM> DemoNames
我运行这个项目,它会进入正确的目录

但是如果我加载导入dll并在单独的测试项目中运行命令
DemoNames
,如下所示:

var parser = new Parser();
parser.UpdateXml();
PM> Import-Module C:\projects\EF.XML\EF.XML.dll
PM> DemoNames
程序转到错误目录,导致以下错误:

获取DemoNames:访问路径“C:\Program Files(x86)\Microsoft” Visual Studio 14.0\Common7\IDE\beheer\u extern\config'被拒绝。在 行:1字符:10
+DemoNames好的,那么您正试图从PackageManager控制台中访问一个在VisualStudio中加载的项目

知道可执行文件是Visual Studio,因此
AppDomain.CurrentDomain.BaseDirectory
将成为Visual Studio安装目录。它绝对不会是当前项目的目录

为了获取当前加载的解决方案的项目目录,您需要通过自动化与正在运行的VisualStudio实例进行交互。通常,可以通过编写扩展或通过VisualStudio核心自动化,即。这很复杂。想这样做吗?你可能得抓起一本关于这个主题的书来读

幸运的是,PMC确实提供了一个cmdlet,它将大大简化这一过程--。它返回,然后您可以使用它获取项目文件的,您可以从中获取目录名

这些是你需要的零件。至于从代码中调用cmdlet,那是另一个问题。

FIX

我设法让它与以下代码一起工作

获取_DemoNames.cs

namespace EF.XML
{
using System;
using System.Linq;
using System.Management.Automation;

[Cmdlet(VerbsCommon.Get, "DemoNames")]
public class Get_DemoNames : PSCmdlet
{

    [Parameter(Position = 0, Mandatory = false)]
    public string prefix;

    protected override void ProcessRecord()
    {

        var names = new[] { "Chris", "Charlie", "Isaac", "Simon" };

        if (string.IsNullOrEmpty(prefix))
        {
            WriteObject(names, true);
        }
        else
        {
            var prefixed_names = names.Select(n => prefix + n);

            WriteObject(prefixed_names, true);
        }

        System.Diagnostics.Debug.Write("hello");

        var parser = new Parser();
        parser.UpdateXml();

    }

  }
}
namespace EF.XML
{
using System;
using System.Linq;
using System.Management.Automation;

[Cmdlet(VerbsCommon.Get, "DemoNames")]
public class Get_DemoNames : PSCmdlet
{

[Parameter(Position = 0, Mandatory = false)]
public string prefix;

protected override void ProcessRecord()
{

    var names = new[] { "Chris", "Charlie", "Isaac", "Simon" };

    if (string.IsNullOrEmpty(prefix))
    {
        WriteObject(names, true);
    }
    else
    {
        var prefixed_names = names.Select(n => prefix + n);

        WriteObject(prefixed_names, true);
    }

    //added
    const string networkPath = "Microsoft.PowerShell.Core\\FileSystem::";
    var currentPath = SessionState.Path.CurrentFileSystemLocation.Path;

    var curProjectDir = currentPath.Substring(networkPath.Length); 

    WriteObject(curProjectDir);

    System.Diagnostics.Debug.Write("hello");

    var parser = new Parser {CurrentProjectDirectory = curProjectDir };
    parser.UpdateXml();

    }

  }
}
Parser.cs

 public class Parser
{
    public void UpdateXml()
    {
                var directoryInfo = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory); // www directory

                var path = Path.Combine(directoryInfo.FullName, @"beheer_extern\config");

                //Creates the beheer_extern\config directory if it doesn't exist, otherwise nothing happens.
                Directory.CreateDirectory(path);

                var instellingenFile = Path.Combine(path, "instellingen.xml");
                var instellingenFileDb = Path.Combine(path, "instellingenDb.xml");

                //Create instellingen.xml if not already existing
                if (!File.Exists(instellingenFile))
                {
                    using (var writer = XmlWriter.Create(instellingenFile, _writerSettings))
                    {
                        var xDoc = new XDocument(
                            new XElement("database", string.Empty, new XAttribute("version", 4)));
                        xDoc.WriteTo(writer);
                    }
                }
      }
}
public class Parser
{    



public string CurrentProjectDirectory{ get; set; }

public void UpdateXml()
{

    var wwwDirectory = Path.Combine(CurrentProjectDirectory, @"www"); // www directory

    var path = Path.Combine(wwwDirectory, @"beheer_extern\config");

    //Creates the beheer_extern\config directory if it doesn't exist, otherwise nothing happens.
    Directory.CreateDirectory(path);

    var instellingenFile = Path.Combine(path, "instellingen.xml");
    var instellingenFileDb = Path.Combine(path, "instellingenDb.xml");

    //Create instellingen.xml if not already existing
    if (!File.Exists(instellingenFile))
    {
        using (var writer = XmlWriter.Create(instellingenFile, _writerSettings))
        {
            var xDoc = new XDocument(
                new XElement("database", string.Empty, new XAttribute("version", 4)));
            xDoc.WriteTo(writer);
        }
    }
  }
}
我还尝试了
EnvDTE
,它同样有效

所需进口:

using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;
获取当前解决方案(路径)的代码:


不要将内容保存在可执行文件的子目录下。您应该在AppData下保存数据。@此解决方案是否应该更新需要在
//www/beheer\u extern/config
中包含xml文件的现有项目。我同意在AppData中保存是更好的做法,但我想要的是可能的吗?您是否在visual studio中的powershell中运行此操作?@我是否会在VS
包管理器控制台中使用
Cmdlet
类和解析器类加载dll
我自己找到了一个修复方法,如果需要,您可以查看我编辑的问题。@Sybren odd,但对你有好处。你不应该在你的问题上加上你的答案。把它作为答案加在这里。等待期结束后,您可以将其选择为正确并结束您的问题。这里就是这样的。另外,如果你能添加更多关于你做了什么以及如何工作的细节,那就太好了。我不明白你的修复程序是如何工作的,我想知道。谢谢。我添加了代码作为答案,我还深入到EnvDTE并将我的“EnvDTE”解决方案添加到了答案中。从我的
Cmdlet
dll中,我可以使用您在我的答案中看到的代码获取当前解决方案,我还可以从当前解决方案中获取
Parser.cs
类(作为
ProjectItem
),方法是:
var p=dte2.solution.FindProjectItem(“Parser.cs”)
但是你知道我如何制作
解析器
实例
p
并调用它的方法(
UpdateXml
)?@Sybren nope。可能是个新问题,如果你不能解决它。好的,没问题,如果我不能找到如何解决它,我会提出一个新问题。