-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Welcome to the altcode.dixon wiki!
In a set-up stage that doesn't need to get run often (except every time on a clean CI VM), copy FxCop from under Visual Studio to some (.gitignored) location within your project. Then copy the appropriate parts from the Dixon NuGet package into the FxCop copy.
Then when running FxCop, use the copy as your executable.
I've used a dummy .csproj to install locally tooling packages that aren't dotnet tool items (things like unit test console runners for .net Framework, or PowerShell modules such as Pester)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
</PropertyGroup>
<ItemGroup>
<None Remove="*.*" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AltCode.Dixon" version="2022.1.8.13182" />
<!-- More packages go here as required -->
</ItemGroup>
</Project>
You need this helper package
nuget BlackFox.VsWhere >= 1.0.0
in your paket directives, and FxCop under a VS2022 install like
let fxcop =
if Environment.isWindows then
BlackFox.VsWhere.VsInstances.getAll ()
|> Seq.filter (fun i -> System.Version(i.InstallationVersion).Major = 17)
|> Seq.map
(fun i ->
i.InstallationPath
@@ "Team Tools/Static Analysis Tools/FxCop")
|> Seq.filter Directory.Exists
|> Seq.tryHead
else
None
Install Dixon (and any other tools) from the dummy project like (replacing {dummy} with whatever you called it
DotNet.restore (fun o ->
{ o with
Packages = [ "./packages" ]
Common = dotnetOptions o.Common }) "./Build/{dummy}.csproj"
and locate these items like
let toolPackages =
let xml =
"./Build/{dummy}.csproj"
|> Path.getFullName
|> XDocument.Load
xml.Descendants(XName.Get("PackageReference"))
|> Seq.filter (fun x -> x.Attribute(XName.Get("Include")) |> isNull |> not)
|> Seq.map
(fun x ->
(x.Attribute(XName.Get("Include")).Value, x.Attribute(XName.Get("version")).Value))
|> Map.ofSeq
let packageVersion (p: string) = p.ToLowerInvariant() + "/" + (toolPackages.Item p)
for example
let dixon =
("./packages/" + (packageVersion "AltCode.Dixon") + "/tools")
|> Path.getFullName
then the local merging can be done like
fxcop
|> Option.iter (fun fx -> Directory.ensure "./packages/fxcop/"
let target = Path.getFullName "./packages/fxcop/"
let prefix = fx.Length
let check t pf (f : string) =
let destination = t @@ (f.Substring pf)
destination |> File.Exists |> not &&
// This ruleset does not play well with `dotnet` libraries
destination |> Path.GetFileName <> "SecurityTransparencyRules.dll"
Shell.copyDir target fx (check target prefix)
Shell.copyDir target dixon (fun _ -> true)
let config = XDocument.Load "./packages/fxcop/FxCopCmd.exe.config"
// Maybe process here...
config.Save "./packages/fxcop/DixonCmd.exe.config"))
)
Just locate the executable(s) as
let (fxcop, dixon) =
if Environment.isWindows then
let expect =
"./packages/fxcop/FxCopCmd.exe"
|> Path.getFullName
if File.Exists expect then
(Some expect, Some ("./packages/fxcop/DixonCmd.exe" |> Path.getFullName))
else
(None, None)
else
(None, None)
and later code to the effect of
if fxcop |> Option.isSome
then FxCop.run
{ FxCop.Params.Create() with
ToolPath = Option.get fxcop
...
for framework-oriented assemblies, or
let nugetCache =
Path.Combine(Environment.GetFolderPath Environment.SpecialFolder.UserProfile, ".nuget/packages")
if dixon |> Option.isSome
then FxCop.run
{ FxCop.Params.Create() with
ToolPath = Option.get dixon
Platform = @"C:\Program Files\dotnet\sdk\{version}\ref" // choose your SDK version
DependencyDirectories = [ // add the obvious dependencies -- the error messages will say which ones
nugetCache @@ "{package1}/{version2}/lib/netstandard2.0"
nugetCache @@ "{package2}/{version2}/lib/netstandard2.0"
...
...
for netstandard2.0 only.
If you're just using the rules assembly with FxCop v17 (vs2022), then there may be a fixable bug.
For the DixonCmd tool for probing netstandard2.0 -- this is a grand lash-up and a hack, and is held together by hope and desperation. There is of course no warranty, nor likelihood of significant bug-fixes.
In the easy cases, the FxCop report file should give some hints as to what dependencies are missing.
Occasionally it may help to create a synthetic platform directory with the netstandard.dll from the SDK ref directory and the mscorlib.dll from the .net Framework, especially if one or the other assembly seems implicated. Occasionally it may help to ensure that debug symbols are not embedded in the assembly under inspection -- consider this if all else fails and the stack trace mentions reading debug information. Occasionally, it may help to build an assembly using netstandard2.0 dependencies under net472 and still use Dixon -- this may help with particularly opaque stack traces, by moving things onto more supported ground.
Alas, in some cases, especially ones involving SecurityPermission attributes there seems to be no good resolution, and at times, not even good error messages -- just E_FAIL status codes from the FxCop assembly reader that may reveal the underlying cause if you use some or all of the "occasionally" tactics mentioned above.