我创建了一个带有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'被拒绝。在 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:访问路径 'C:\ Windows \ system32 \ beheer_extern \ config'被拒绝。在线:1 焦炭: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 :(得分:0)
好的,所以你试图从包管理器控制台中访问Visual Studio中加载的项目。
知道可执行文件是 Visual Studio ,因此AppDomain.CurrentDomain.BaseDirectory
将成为Visual Studio安装目录。 绝对 不会是当前项目的目录。
为了获取当前加载的解决方案的项目目录,您需要通过自动化与正在运行的Visual Studio实例进行交互。通常,这是通过编写扩展或通过Visual Studio核心自动化来完成的,AKA EnvDTE com object。这是复杂。想要这样做吗?你可能不得不抓一本关于这个主题的书并阅读。
幸运的是,PMC确实提供了一个cmdlet,可以为您极大地简化这一过程 - get-project。它返回DTE representation of the project,然后您可以使用它来获取项目文件full filename,从中可以获取目录名称。
这些是你需要的零件。至于从代码中调用cmdlet,这是另一个问题。
答案 1 :(得分: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);
}