2015-10-21 3 views
-1

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

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

И я бегу проект он идет на правильные каталоги.

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

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

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

Get-DemoNames : Access to the path 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\beheer_extern\config' is denied. At line:1 char:10 + DemoNames <<<< + CategoryInfo : NotSpecified: (:) [Get-DemoNames], UnauthorizedAccessException + FullyQualifiedErrorId : System.UnauthorizedAccessException,EF.XML.Get_DemoNames

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

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

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

Get-DemoNames : Access to the path 'C:\Windows\system32\beheer_extern\config' is denied. At line:1 char:10 + DemoNames <<<< + CategoryInfo : NotSpecified: (:) [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)?

+0

Не сохранять вещи в подкаталоге исполняемого файла. Вы должны сохранять данные в AppData. – Will

+0

@Will Это решение должно обновлять существующие проекты, которые должны иметь xml-файлы в '// www/beheer_extern/config'. Я согласен, что лучше практиковать сохранение в AppData, но это то, что я хочу сделать возможным? – Sybren

+0

Вы используете это в powershell в визуальной студии? – Will

ответ

0

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

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

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

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

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

+0

. Я буду смотреть на это tommorow спасибо за ваш ответ. – Sybren

+0

Я нашел исправление самостоятельно, вы можете посмотреть, если хотите, посмотреть мой отредактированный вопрос. – Sybren

+0

@Sybren странно, но хорошо для вас. Вы не должны добавлять свой ответ на свой вопрос. Просто добавьте его в качестве ответа здесь. После периода ожидания вы можете выбрать его как правильно и закрыть свой вопрос. Так оно и делается здесь. Кроме того, если вы могли бы добавить дополнительные сведения о * what *, которые вы сделали, и о том, как это работает, это было бы здорово. Я не понимаю, как ваше исправление будет работать, и хотелось бы знать. Благодарю. – Will

0

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); 
     } 
Смежные вопросы