Kirsten
Kirsten

Reputation: 18066

MSBUILD : error MSB1003: Specify a project or solution file

The instructions for a sample application that I am trying to build as me to type

dotnet restore

at the command line.

dotnet --version

reports

2.1.300

When I do this, I get the following error:

MSBUILD : error MSB1003: Specify a project or solution file.
The current working directory does not contain a project or solution file.

The folder I am executing the command in contains .cs files, but no .sln or .csproj file.

Does .NET Core require a .csproj file?

The code comes from an answer to my question here but the github project has since been deleted.

I did try creating a .csproj file, but i had trouble guessing what packages to put in it.

I added the following .csproj file:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>

</Project>

Then I get the following namespaces missing:

 Microsoft.IdentityModel
 Azure
 KeyVaultClient
 ClientAssertinCertificate
 Newtonsoft
 Org

I know how to use package manager, but how do I figure out the right versions of everything?

Here is file program.cs:

using System;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Azure.KeyVault;
using Microsoft.IdentityModel.Clients.ActiveDirectory;

namespace dotnetconsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(@"This Application must be run after running the powershell script Setup.ps1!
                                This DotNet Console Application authenticates to Key Vault!
                                It also creates a Secret Key Value Pair!
                                And then it gets the Secret Key Value Pair!");

            bool isWindows = System.Runtime.InteropServices.RuntimeInformation
                                               .IsOSPlatform(OSPlatform.Windows);
            string KEYVAULT_URI = String.Empty;
            string APPLICATION_ID = String.Empty;
            string CERT_THUMBPRINT = String.Empty;
            if(isWindows)
            {
                KEYVAULT_URI = System.Environment.GetEnvironmentVariable("VAULT_NAME", EnvironmentVariableTarget.User);
                APPLICATION_ID = System.Environment.GetEnvironmentVariable("APPLICATION_ID", EnvironmentVariableTarget.User);
                CERT_THUMBPRINT = System.Environment.GetEnvironmentVariable("CERT_THUMBPRINT", EnvironmentVariableTarget.User);
            }
            else
            {
                var result = GetVariablesFromJSON();
                APPLICATION_ID = result.Item1;
                CERT_THUMBPRINT = result.Item2;
                KEYVAULT_URI = result.Item3;
            }
            KeyVault keyVaultObj = new KeyVault(APPLICATION_ID, CERT_THUMBPRINT);
            var VaultName = "https://" + KEYVAULT_URI + ".vault.azure.net/";
            var waitHandle = keyVaultObj.CreateSecretKeyValuePair(VaultName);
            Console.WriteLine("Vault URI is! {0}", VaultName);
            Console.WriteLine("Wait method is invoked to wait for Secret Key Value pair to be created");
            waitHandle.Wait();
            Console.WriteLine("Secret Key Value pair is now created");
            keyVaultObj.GetResult(VaultName);
        }

        private static Tuple<string, string, string> GetVariablesFromJSON()
        {
            var ServicePrincipalJSON = Directory.GetCurrentDirectory() + "/ServicePrincipal.json";
            var CertThumbprintJSON = Directory.GetCurrentDirectory() + "/CertThumbprint.txt";
            var VaultJSON = Directory.GetCurrentDirectory() + "/KeyVault.json";
            if(File.Exists(ServicePrincipalJSON) && File.Exists(CertThumbprintJSON) && File.Exists(VaultJSON))
            {
                return new Tuple<string, string, string>(ProcessFile(ServicePrincipalJSON, "appId", true), ProcessFile(CertThumbprintJSON, "", false), ProcessFile(VaultJSON, "name", true));
            }

            return new Tuple<string, string, string>("", "", "");
        }

        private static string ProcessFile(string fileName, string valueToLookFor, bool isJson)
        {
            var result = "";
            using (StreamReader ContentsOfFile = File.OpenText(fileName))
            {
                if(isJson){
                    var stuff = (JObject)JsonConvert.DeserializeObject(ContentsOfFile.ReadToEnd());
                    result = stuff[valueToLookFor].Value<string>();
                }
                else {
                    var contents = ContentsOfFile.ReadToEnd();
                    contents = contents.Split("=")[1];
                    result = Regex.Replace(contents, @"\t|\n|\r", "");
                }
            }
            return result;
        }
    }
}

Here is Util.cs

using System;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;

public class Util
{
    public static X509Certificate2 ConvertFromPfxToPem(string filename)
    {
        using (System.IO.FileStream fs = System.IO.File.OpenRead(filename))
        {
            byte[] data = new byte[fs.Length];
            byte[] res = null;
            fs.Read(data, 0, data.Length);
            if (data[0] != 0x30)
            {
                res = GetPem("CERTIFICATE", data);
            }
            X509Certificate2 x509 = new X509Certificate2(res); //Exception hit here
            return x509;
        }
    }

    private static byte[] GetPem(string type, byte[] data)
    {
        string pem = Encoding.UTF8.GetString(data);
        string header = String.Format("-----BEGIN {0}-----", type);
        string footer = String.Format("-----END {0}-----", type);
        int start = pem.IndexOf(header) + header.Length;
        int end = pem.IndexOf(footer, start);
        string base64 = pem.Substring(start, (end - start));
        base64 = base64.Replace(System.Environment.NewLine, "");
        base64 = base64.Replace('-', '+');
        base64 = base64.Replace('_', '/');
        return Convert.FromBase64String(base64);
    }

    public static RSACryptoServiceProvider PemFileReader(){
        RsaPrivateCrtKeyParameters keyParams;
        using (var reader = File.OpenText("cert.pem")) // file containing RSA PKCS1 private key
        {
            keyParams = ((RsaPrivateCrtKeyParameters)new PemReader(reader).ReadObject());
        }

        RSAParameters rsaParameters = new RSAParameters();

        rsaParameters.Modulus = keyParams.Modulus.ToByteArrayUnsigned();
        rsaParameters.P = keyParams.P.ToByteArrayUnsigned();
        rsaParameters.Q = keyParams.Q.ToByteArrayUnsigned();
        rsaParameters.DP = keyParams.DP.ToByteArrayUnsigned();
        rsaParameters.DQ = keyParams.DQ.ToByteArrayUnsigned();
        rsaParameters.InverseQ = keyParams.QInv.ToByteArrayUnsigned();
        rsaParameters.D = keyParams.Exponent.ToByteArrayUnsigned();
        rsaParameters.Exponent = keyParams.PublicExponent.ToByteArrayUnsigned();

        RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(2048);
        rsaKey.ImportParameters(rsaParameters);
        return rsaKey;
    }
}

Here is KeyVault.cs

using System;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.Azure.KeyVault;
using System.Threading.Tasks;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Azure.KeyVault.Models;
using System.Runtime.InteropServices;
using System.Security.Cryptography;

namespace dotnetconsole
{
    public class KeyVault
    {
        KeyVaultClient _keyVaultClient;
        string APPLICATION_ID, CERT_THUMBPRINT;
        public KeyVault(string APPLICATION_ID, string CERT_THUMBPRINT) {
            this.APPLICATION_ID = APPLICATION_ID;
            this.CERT_THUMBPRINT = CERT_THUMBPRINT;
            _keyVaultClient = new KeyVaultClient(this.GetAccessToken);
        }

        public static ClientAssertionCertificate AssertionCert { get; set; }

        // This method is used to get a token from Azure Active Directory.
        public async Task<string> GetAccessToken(string authority, string resource, string scope)
        {
            var context = new AuthenticationContext(authority, TokenCache.DefaultShared);
            bool isWindows = System.Runtime.InteropServices.RuntimeInformation
                                               .IsOSPlatform(OSPlatform.Windows);

            X509Certificate2 certByThumbprint = new X509Certificate2();
            if(isWindows){
                certByThumbprint = FindCertificateByThumbprint(this.CERT_THUMBPRINT);
            } else {
                // If it's a pem file then we take the private key portion and create a
                // RSACryptoServiceProvider and then we create a x509Certificate2 class from the cert portion
                // and then we combine them both to become one x509Certificate2
                RSACryptoServiceProvider rsaCryptoServiceProvider = Util.PemFileReader();
                certByThumbprint = Util.ConvertFromPfxToPem("cert.pem");
                certByThumbprint = certByThumbprint.CopyWithPrivateKey(rsaCryptoServiceProvider);
            }

            AssertionCert = new ClientAssertionCertificate(this.APPLICATION_ID, certByThumbprint);
            var result = await context.AcquireTokenAsync(resource, AssertionCert);
            return result.AccessToken;
        }


        public async Task CreateSecretKeyValuePair(string vaultBaseURL)
        {
            System.Console.WriteLine("Authenticating to Key Vault using ADAL Callback to create Secret Key Value Pair");
            System.Console.WriteLine(vaultBaseURL);
            KeyVaultClient kvClient = new KeyVaultClient(this.GetAccessToken);
            await kvClient.SetSecretAsync(vaultBaseURL, "TestKey", "TestSecret");
        }

        // In this method we first get a token from Azure Active Directory by using the self signed cert we created in our powershell commands
        // And then we pass that token to Azure Key Vault to authenticate the service principal to get access to the secrets
        // Finally we retrieve the secret value that was created previously
        public void GetResult(string keyvaultUri)
        {
            try
            {
                var result = this._keyVaultClient.GetSecretAsync(keyvaultUri, "TestKey").Result.Value;
                System.Console.WriteLine("Secret Key retrieved is {0} and value is {1}, ", "TestKey", result);
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        // In Windows this method would find the certificate that's stored in the certificate manager under current user
        // Given a thumbprint this method finds the certificate
        public static X509Certificate2 FindCertificateByThumbprint(string findValue)
        {
            X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            try
            {
                store.Open(OpenFlags.ReadOnly);
                X509Certificate2Collection col = store.Certificates.Find(X509FindType.FindByThumbprint,
                    findValue, false); // Don't validate certs, since the test root isn't installed.
                if (col == null || col.Count == 0 )
                    return null;
                return col[0];
            }
            finally
            {
                store.Close();
            }
        }
    }
}

[Update] Now I can run dotnet restore but dotnet run gives errors

As follows

KeyVault.cs(2,17): error CS0234: The type or namespace name 'IdentityModel' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]
    KeyVault.cs(3,17): error CS0234: The type or namespace name 'Azure' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]
    KeyVault.cs(6,17): error CS0234: The type or namespace name 'Azure' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]
    Program.cs(3,7): error CS0246: The type or namespace name 'Newtonsoft' could not be found (are you missing a using directive or an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]
    Program.cs(4,7): error CS0246: The type or namespace name 'Newtonsoft' could not be found (are you missing a using directive or an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]
    Program.cs(10,17): error CS0234: The type or namespace name 'Azure' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]
    Program.cs(11,17): error CS0234: The type or namespace name 'IdentityModel' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]
    Util.cs(7,7): error CS0246: The type or namespace name 'Org' could not be found (are you missing a using directive or an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]
    Util.cs(8,7): error CS0246: The type or namespace name 'Org' could not be found (are you missing a using directive or an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]
    Util.cs(9,7): error CS0246: The type or namespace name 'Org' could not be found (are you missing a using directive or an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]
    Util.cs(10,7): error CS0246: The type or namespace name 'Org' could not be found (are you missing a using directive or an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]
    Util.cs(11,7): error CS0246: The type or namespace name 'Org' could not be found (are you missing a using directive or an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]
    KeyVault.cs(22,23): error CS0246: The type or namespace name 'ClientAssertionCertificate' could not be found (are you missing a using directive or an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]
    KeyVault.cs(14,9): error CS0246: The type or namespace name 'KeyVaultClient' could not be found (are you missing a using directive or an assembly reference?) [C:\dev2018\key-vault-dotnet-quickstart\MyKeyVault.csproj]

    The build failed. Please fix the build errors and run again.

[Update]

Tools ->Nuget Package Manager -> Manage Packages for solution reports an error

Microsoft Visual Studio
The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))

[Update]

I saved everything, closed the .sln file and reopened it. Then I was able to get into Nuget Package Manager.

[Update]

I have installed Microsoft.Azure.KeyVault(3.0.0) and Newtonsoft.Json(11.0.2) I am having problems with Microsoft.IdentityModel.Clients.ActiveDirectory When I tried Microsoft.IdentityModel it was the wrong framework.

Package 'Microsoft.IdentityModel 6.1.7600.16394' was restored using ''.NETFramework, Version=v4.61'
instead of the projecttargetframework '.NETCoreApp,Version=v2.1'
This package may not be fully compatible with your project

[Update] Googled "using Microsoft.IdentityModel.Clients.ActiveDirectory core"

Found this link and ran in PM

Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory -Version 3.19.8

[Update] Tried googling the Bouncy Castle using statement and found

Install-Package BouncyCastle.NetCore -Version 1.8.2

[Update]

Rebuild All succeeds, now I have a run time error in line 47 of

var waitHandle = keyVaultObj.CreateSecretKeyValuePair(VaultName);

  System.AggregateException
  HResult=0x80131500
  Message=One or more errors occurred.
  Source=System.Private.CoreLib
  StackTrace:
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at dotnetconsole.Program.Main(String[] args) in C:\dev2018\key-vault-dotnet-quickstart\Program.cs:line 47

Inner Exception 1:
ArgumentNullException: Value cannot be null.

Upvotes: 20

Views: 96127

Answers (3)

user1585204
user1585204

Reputation: 965

The error is saying exactly how to fix it: "MSBUILD : error MSB1003: Specify a project or solution file. The current working directory does not contain a project or solution file." Just to show I'm not preaching, I read through all the other posts here, in Git Hub and on another site.

Then looked at my project structure:

  1. I have my test project
  2. In the project is my added folder for my tests created for the XUnit course I'm doing
  3. Realized my tests are 1 level down from the proj root.

The csproj file or .sln file will be a level up.

Finally xcopied my tests out of the folder, into the root proj directory. Removed the now empty folder. Ran the tests from the command line:

> PS C:\ProjectsDoIT\CA_DOITTUIT\CADOITTUIT\SeleniumTests> dotnet test --filter Category=AwardsForm
Restore succeeded with 2 warning(s) in 0.4s
    C:\ProjectsDoIT\CA_DOITTUIT\CADOITTUIT\SeleniumTests\SeleniumTests.csproj : warning NU1608: Detected package version outside of dependency constraint: xunit.core 2.4.1 requires xunit.extensibility.core (= 2.4.1) but version xunit.extensibility.core 2.7.0 was resolved.
    C:\ProjectsDoIT\CA_DOITTUIT\CADOITTUIT\SeleniumTests\SeleniumTests.csproj : warning NU1608: Detected package version outside of dependency constraint: xunit.core 2.4.1 requires xunit.extensibility.execution (= 2.4.1) but version xunit.extensibility.execution 2.7.0 was resolved.
  SeleniumTests succeeded with 5 warning(s) (6.3s) → bin\Debug\net6.0\SeleniumTests.dll
    C:\ProjectsDoIT\CA_DOITTUIT\CADOITTUIT\SeleniumTests\SeleniumTests.csproj : warning NU1608: Detected package version outside of dependency constraint: xunit.core 2.4.1 requires xunit.extensibility.core (= 2.4.1) but version xunit.extensibility.core 2.7.0 was resolved.
    C:\ProjectsDoIT\CA_DOITTUIT\CADOITTUIT\SeleniumTests\SeleniumTests.csproj : warning NU1608: Detected package version outside of dependency constraint: xunit.core 2.4.1 requires xunit.extensibility.execution (= 2.4.1) but version xunit.extensibility.execution 2.7.0 was resolved.
    C:\ProjectsDoIT\CA_DOITTUIT\CADOITTUIT\SeleniumTests\TestCommon.cs(12,27): warning CS8618: Non-nullable property 'MyDriver' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.
    C:\ProjectsDoIT\CA_DOITTUIT\CADOITTUIT\SeleniumTests\DoITSubmitAwardShould.cs(369,21): warning xUnit1013: Public method 'Dispose' on test class 'DoITSubmitAwardShould' should be marked as a Fact. (https://xunit.github.io/xunit.analyzers/rules/xUnit1013)
    C:\ProjectsDoIT\CA_DOITTUIT\CADOITTUIT\SeleniumTests\AddShoutOutTest_FromSeCourse.cs(52,5): warning xUnit2000: The literal or constant value "got here" should be passed as the 'expected' argument in the call to 'Assert.Equal(expected, actual)' in method 'AddShoutOut' on type 'SuiteTests'. (https://xunit.github.io/xunit.analyzers/rules/xUnit2000)
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.3+1b45f5407b (64-bit .NET 6.0.36)
[xUnit.net 00:00:00.71]   Discovering: SeleniumTests
[xUnit.net 00:00:00.77]   Discovered:  SeleniumTests
[xUnit.net 00:00:00.77]   Starting:    SeleniumTests
Starting Microsoft Edge WebDriver 131.0.2903.86 (cf5bf303997cad93d7a0bede234d3c3dc01cc63d) on port 53683
To submit feedback, report a bug, or suggest new features, please visit https://github.com/MicrosoftEdge/EdgeWebDriver
Only local connections are allowed.
Please see https://aka.ms/WebDriverSecurity for suggestions on keeping Microsoft Edge WebDriver safe.
Microsoft Edge WebDriver was started successfully.
msedgedriver was started successfully on port 53683.
[xUnit.net 00:00:14.14]   Finished:    SeleniumTests
  SeleniumTests test succeeded (15.5s)

Test summary: total: 1, failed: 0, succeeded: 1, skipped: 0, duration: 15.5s
Build succeeded with 7 warning(s) in 22.7s
PS C:\ProjectsDoIT\CA_DOITTUIT\CADOITTUIT\SeleniumTests>

Upvotes: 0

Kirsten
Kirsten

Reputation: 18066

The error was occurring, because I didn't have any .csproj file. The author had not included it in the source code.

The question documents the steps I went through constructing one.

Upvotes: 26

Oleksii Sokol
Oleksii Sokol

Reputation: 161

In my case, I needed to specify the full path to the .csproj file

Upvotes: 0

Related Questions