Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Maverick.PCF.Builder.Helper/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,16 @@ public static string Check()
return $"pac";
}

/// <summary>
/// Check PAC using custom path
/// </summary>
/// <param name="pacPath">Full path to pac.exe</param>
/// <returns></returns>
public static string Check(string pacPath)
{
return $"\"{pacPath}\"";
}

/// <summary>
/// pac auth create --url <https://xyz.crm.dynamics.com>
/// </summary>
Expand Down
77 changes: 75 additions & 2 deletions Maverick.PCF.Builder/PCFBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public partial class PCFBuilder : PluginControlBase, IGitHubPlugin, IHelpPlugin,
{
#region XrmToolBox settings
private Settings pluginSettings;
private string detectedPacPath; // Cache the detected PAC path for session reuse

public string RepositoryName => "PCF-CustomControlBuilder";
public string UserName => "Power-Maverick";
Expand Down Expand Up @@ -800,8 +801,30 @@ public void CheckPacVersion(object worker, DoWorkEventArgs args)
{
var start = DateTime.Now;

string[] commands = new string[] { Commands.Pac.Check() };
var output = CommandLineHelper.RunCommand(commands);
// Try to find PAC in multiple locations
string pacPath = FindPacPath();
string[] commands;
string output;

if (!string.IsNullOrEmpty(pacPath))
{
// Use the found PAC path
if (pacPath.Equals("pac", StringComparison.InvariantCultureIgnoreCase))
{
commands = new string[] { Commands.Pac.Check() };
}
else
{
commands = new string[] { Commands.Pac.Check(pacPath) };
}
output = CommandLineHelper.RunCommand(commands);
}
else
{
// Fallback to standard check for backward compatibility
commands = new string[] { Commands.Pac.Check() };
output = CommandLineHelper.RunCommand(commands);
}

StringHelper stringer = new StringHelper();
PacVersionParsedDetails outputParsedPacDetails = stringer.ParsePacVersionOutput(output);
Expand Down Expand Up @@ -934,6 +957,56 @@ private string FindMsBuildPath()
return msBuildPath;
}

private string FindPacPath()
{
// Return cached path if available
if (!string.IsNullOrEmpty(detectedPacPath))
{
return detectedPacPath;
}

// First try the standard PAC command (global installation)
string[] standardCommands = new string[] { Commands.Pac.Check() };
var standardOutput = CommandLineHelper.RunCommand(standardCommands);

StringHelper stringer = new StringHelper();
PacVersionParsedDetails standardPacDetails = stringer.ParsePacVersionOutput(standardOutput);
Comment on lines +969 to +973
Copy link

Copilot AI Sep 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The PAC checking logic is duplicated between FindPacPath() and CheckPacVersion() methods. Consider extracting this into a private helper method to reduce code duplication and improve maintainability.

Copilot uses AI. Check for mistakes.

// If PAC is found via standard command, use it
if (!standardPacDetails.CLINotFound)
{
detectedPacPath = "pac"; // Cache the result
return detectedPacPath;
}

// Try VS Code extension location
try
{
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string vscodeExtensionPacPath = Path.Combine(appDataPath, "Code", "User", "globalStorage", "microsoft-isvexptools.powerplatform-vscode", "pac", "tools", "pac.exe");

if (File.Exists(vscodeExtensionPacPath))
{
// Test if this PAC installation works by running it
string[] vscodeCommands = new string[] { Commands.Pac.Check(vscodeExtensionPacPath) };
var vscodeOutput = CommandLineHelper.RunCommand(vscodeCommands);

PacVersionParsedDetails vscodePacDetails = stringer.ParsePacVersionOutput(vscodeOutput);
if (!vscodePacDetails.CLINotFound)
{
detectedPacPath = vscodeExtensionPacPath; // Cache the result
return detectedPacPath;
}
}
}
catch (Exception)
{
// If there's any error accessing the VS Code extension path, continue with standard behavior
}
Comment on lines +1002 to +1005
Copy link

Copilot AI Sep 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Catching all exceptions with a generic Exception catch block is discouraged. Consider catching specific exceptions like UnauthorizedAccessException, DirectoryNotFoundException, or PathTooLongException to handle only the expected error scenarios.

Suggested change
catch (Exception)
{
// If there's any error accessing the VS Code extension path, continue with standard behavior
}
catch (UnauthorizedAccessException)
{
// If there's any error accessing the VS Code extension path, continue with standard behavior
}
catch (DirectoryNotFoundException)
{
// If there's any error accessing the VS Code extension path, continue with standard behavior
}
catch (PathTooLongException)
{
// If there's any error accessing the VS Code extension path, continue with standard behavior
}

Copilot uses AI. Check for mistakes.

return string.Empty; // PAC not found in any location
}

private void IncrementComponentVersion()
{
var start = DateTime.Now;
Expand Down