AppDomain.CurrentDomain.BaseDirectory изменяется на неправильный каталог

Я создал dll с Cmdlet команда (см. Get_DemoNames.cs). Из этого cmdlet Я называю метод UpdateXml()пока все работает. Но UpdateXml() также создает файлы, если они не существуют. Когда я звоню UpdateXml() в файле класса, как это:

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

И я запускаю проект, он идет в правильные каталоги.

Но если я загружаю импорт dll и запускаю команду DemoNames в отдельном тестовом проекте, как это:

PM> Import-Module C:\projects\EF.XML\EF.XML.dll
PM> DemoNames

Программа переходит в неправильный каталог, что приводит к следующей ошибке:

Get-DemoNames: доступ к пути "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\beheer_extern\config" запрещен. В строке:1 символ:10 + DemoNames <<<< + CategoryInfo: Не указано: (:) [Get-DemoNames], UnauthorizedAccessException + FullyQualifiedErrorId: System.UnauthorizedAccessException,EF.XML.Get_DemoNames

Я искал в сети эту ошибку и обнаружил, что некоторые другие смогли решить ее, добавив эту строку в конструктор:

public Parser()
{
    AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory);
}

Это дает мне другой неправильный путь:

Get-DemoNames: доступ к пути "C:\Windows\system32\beheer_extern\config" запрещен. В строке:1 символ:10 + DemoNames <<<< + CategoryInfo: Не указано: (:) [Get-DemoNames], UnauthorizedAccessException + FullyQualifiedErrorId: System.UnauthorizedAccessException,EF.XML.Get_DemoNames

Get_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();

    }

  }
}

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);
                    }
                }
      }
}

Как я могу получить правильный каталог проекта (www каталог)?

2 ответа

Итак, вы пытаетесь получить доступ к проекту, загруженному в Visual Studio, из консоли диспетчера пакетов.

Знайте, что исполняемый файл Visual Studio, и так AppDomain.CurrentDomain.BaseDirectory будет каталог установки Visual Studio. Это абсолютно не будет каталогом текущего проекта.

Чтобы получить каталог проекта для загруженного в данный момент решения, вам нужно взаимодействовать с работающим экземпляром Visual Studio с помощью автоматизации. Обычно это делается путем написания расширения или посредством автоматизации ядра Visual Studio, также называемой com-объектом EnvDTE. Это сложно. Хочешь сделать это? Возможно, вам придется взять книгу на эту тему и прочитать.

К счастью, PMC действительно предоставляет командлет, который значительно упростит это для вас - get-project. Он возвращает представление проекта в DTE, которое затем можно использовать для получения полного имени файла файла проекта, из которого можно получить имя каталога.

Это те части и детали, которые вам нужны. Что касается вызова командлета из вашего кода, это другой вопрос.

FIX

Мне удалось заставить его работать со следующим кодом

Get_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);
    }

    //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 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;

Код для получения текущего решения (путь):

 DTE2 dte2 = Package.GetGlobalService(typeof(DTE)) as DTE2;

        if (dte2 != null)
        {
            WriteObject(dte2.Solution.FullName);
        }
Другие вопросы по тегам