"Access to path [...] is denied" even when I Run as Administrator - c#

My program is not liking my File.Copy, as it says
Access to the path 'C:\Users\Me\Documents\Visual Studio
2013\Projects\Unfriendly\Unfriendly\bin\Debug\Data' is denied
when I try to invoke my function
public void AddFriendList ( string newDataPath )
{
// dataPath: Full file path to Facebook data file being added
string newFriendsPath = System.IO.Path.Combine(new string [] { newDataPath,"html","friends.htm"});
using ( StreamReader sr = new StreamReader(this._datadir) )
{
Match friendsULs = DataReader._lregx.Match(sr.ReadToEnd());
if ( !friendsULs.Success )
{
throw new Exception(String.Format("Couldn't find exactly one piece of HTML matching regex {0}",
DataReader._lregx.ToString()));
}
Dictionary<string, int> friendMap = new Dictionary<string, int>();
foreach ( Match thisFriendRegex in DataReader._fregx.Matches(friendsULs.ToString()) )
{
var thisFriendString = thisFriendRegex.ToString();
if ( friendMap.ContainsKey(thisFriendString) )
{
++friendMap[thisFriendString];
}
else
{
friendMap[thisFriendString] = 1;
}
_fhist.Add(new FriendList { friendNames = friendMap, timestamp = File.GetCreationTime(newFriendsPath) });
}
}
// Copy new data Facebook data into repository
File.Copy(newDataPath, this._datadir);
}
with newDataPath being C:\Users\Me\Desktop\facebook_data. I've tried Run as Administrator and still get the error.
The full meat of my project can be seen at https://github.com/jamkin/Unfriendly/blob/master/Unfriendly/DataReader.cs and, by the way, it looks like GitHub doesn't know what to do with #"..." strings since it's making everything blue after
private static readonly string _instructsBody = String.Format(#"AddFriendList <FacebookDataPath>: Adds to reposistory the instance of Facebook data found at FacebookDataPath\n
Example usage: AddFriendList C:\Users\Jamin\Desktop\facebook_data_1\n
{0}\n
PrintInstructions: Prints instructions (like you just did!)\n
{0}\n
CompareLastTwo: Shows difference between latest two friends lists in repository",
new String('-', DataReader._instructsHeader.Length));
Is there a way to write that and not confuse GitHub?

Related

Autodesk Forge Design Automation - Inventor - failedInstructions (FailedMissingOutput)

I am trying to use the WorkItems API to extract key paramaters of a part to a text file. The work item fails with FailedMissingOutput [KeyParameters.txt] which is the file my plugin creates in the working folder. Debugging locally the file is created successfully.
Log:
Addin Code is pretty simple:
public void RunWithArguments(Document doc, NameValueMap map)
{
LogTrace("Processing " + doc.FullFileName);
LogInputData(doc, map);
try
{
var DocDir = System.IO.Path.GetDirectoryName(doc.FullFileName);
var ParametersOutputFileName = System.IO.Path.Combine(DocDir, "KeyParameters.txt");
if (doc.DocumentType == DocumentTypeEnum.kPartDocumentObject)
{
using (new HeartBeat())
{
// TODO: handle the Inventor part here
PartDocument PartDoc = (PartDocument)doc;
ExtractKeyParams(PartDoc.ComponentDefinition.Parameters, ParametersOutputFileName);
}
}
else if (doc.DocumentType == DocumentTypeEnum.kAssemblyDocumentObject) // Assembly.
{
using (new HeartBeat())
{
// TODO: handle the Inventor assembly here
AssemblyDocument AssyDoc = (AssemblyDocument)doc;
ExtractKeyParams(AssyDoc.ComponentDefinition.Parameters, ParametersOutputFileName);
}
}
}
catch (Exception e)
{
LogError("Processing failed. " + e.ToString());
}
}
public void ExtractKeyParams(Parameters Params, string OutputFileName)
{
List<string> ParamList = new List<string>();
foreach (Parameter Param in Params)
{
if (Param.IsKey)
{
ParamList.Add(Param.Name);
}
}
string[] OutputParams = ParamList.ToArray();
System.IO.File.AppendAllLines(OutputFileName, OutputParams);
}
Activity Params...
private static Dictionary<string, Parameter> GetActivityParams()
{
return new Dictionary<string, Parameter>
{
{
Constants.Parameters.InventorDoc,
new Parameter
{
Verb = Verb.Get,
Description = "File to process"
}
},
{
"OutputParams",
new Parameter
{
Verb = Verb.Put,
LocalName = "KeyParameters.txt",
Description = "Key Parameters Output",
Ondemand = false,
Required = false
}
}
};
}
.....And Work Item arguments (With token and ids removed), the signed resource is a forge bucket resource generated to expire in 60 minutes so that shouldn't be the issue,
private static Dictionary<string, IArgument> GetWorkItemArgs()
{
Dictionary<string, string> Header = new Dictionary<string, string>();
Header.Add("Authorization", "Bearer <ACCESS_TOKEN>");
Dictionary<string, string> Header2 = new Dictionary<string, string>();
Header2.Add("Authorization", "Bearer <ACCESS_TOKEN>");
Header2.Add("Content-type", "application/octet-stream");
return new Dictionary<string, IArgument>
{
{
Constants.Parameters.InventorDoc,
new XrefTreeArgument
{
Url = "https://developer.api.autodesk.com/oss/v2/buckets/<BUCKET_KEY>/objects/box.ipt",
Headers = Header
}
},
{
"OutputParams",
new XrefTreeArgument
{
Verb = Verb.Put,
Url = "https://developer.api.autodesk.com/oss/v2/signedresources/<SIGNED_RESOURCE_ID>?region=US",
Headers = Header2
}
}
};
}
I cannot work out why the KeyParameters.txt file isn't being generated by my addin, but looking at the log it seems it is and maybe the problem is uploading it to the signed resource, my token has all the needed scopes.
The KeyParameters.txt file isn't generated because your Activity calls this function Run(Document doc). It is possible to see it in your log, check this line:
InventorCoreConsole.exe Information: 0 : Run called with box.ipt
Now just try to move your code to the Run(Document doc) function.
The RunWithArguments(Document doc, NameValueMap map) function is called in case that you have any arguments in the command line in your Activity.
https://forge.autodesk.com/en/docs/design-automation/v3/developers_guide/field-guide/#command-lines
From the error message it seems like your addin is either not generating the "KeyParameters.txt" file or generating it at the wrong location.
Is it possible that your code never enter any of the if statement or it end up in the catch statement without creating the txt file?
You can download the report using the reportUrl, there might be more information in there. You might also be able to add more logging in there to help you understand what is happening.

Why are my strings not being validated by double equals and characters are not being appended as they should to the end

So I am a Software Packager and I am working on a little project for my company to automate the packaging of some of the free software available via Ninite and Chocolatey. I have managed to get the Ninite stuff working fine but Chocolatey is proving to be a pain.
This section of the code is supposed to compare the app versions from my .csv to data returned from querying chocolatey via cmd.exe.
If the versions don't match I have some other classes that deal with updating the .csv with the latest available version and the rest of the code creates some config files to be used by the other software I am dealing with. This bit is irrelevant as I have managed to get it to work. It's simply just the fact that for some unknown reason the strings returned from querying chocolatey are not behaving as they should.
I initially thought the issue may have been caused by the way I was using .Replace() to filter unwanted data but at this point if I remove all instances of .Replace() and just simply use the data stored in line I get the same results.
The issue seems to lay somewhere in the GetChocApps() method and the print outs are from the CompareVersions() method.
(Sorry if I have provided a tad more code than I should have but I personally thought it was all relevant)
using System;
using System.Diagnostics;
using System.IO;
using System.Collections.Generic;
namespace XXXX_PackagingAutomation
{
class Choc
{
private Dictionary<string, string> chocApps = new Dictionary<string, string>();
private Dictionary<string, string> csvApps = new Dictionary<string, string>();
// For each app a new entry is to be added
// Key: Name in Chocolatey
// Value: Name to appear in CSV
private Dictionary<string, string> chocAppsToCheck = new Dictionary<string, string>() {
{"adobereader", "Adobe_Acrobat_Reader_DC"}
};
private List<Data> csvData; // Used to hold csv data passed in from Main method
#region Run
public void Run(List<Data> csvDataIn)
{
csvData = csvDataIn;
GetChocApps();
CsvAppsToDic(); // Place all the CSV apps along with corresponding versions to csvApps dictionary
CompareVersions();
}
#endregion
#region Get Choc Apps
private void GetChocApps()
{
foreach (var appName in chocAppsToCheck)
{
List<string> chocoTempList = new List<string>();
ProcessStartInfo procStartInfo = new ProcessStartInfo()
{
FileName = "cmd.exe",
Arguments = $"/c choco search {appName.Key} --exact",
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
};
//Process.Start(procStartInfo);
Process p = new Process();
p.StartInfo = procStartInfo;
p.Start();
StreamReader outputWriter = p.StandardOutput;
string errorReader = p.StandardError.ReadToEnd();
string lines = outputWriter.ReadToEnd();
string[] individualLines = lines.Split("\n"[0]);
// All lines returned from the command are then added to the chocoTempList
foreach (string line in individualLines)
chocoTempList.Add(line);
p.WaitForExit();
foreach (string line in chocoTempList)
{
// If the line contains the information we are looking for then we add it to the choco dictionaries
if (!line.Contains("Chocolatey v") && !line.Contains("packages found") && line.Contains(appName.Key))
{
#region Adobe Acrobat Reader DC
if (appName.Key == "adobereader")
{
// Filter the line to exclude anything else other than the version which is what we want
// and then assign it to the version variable.
string version = line.Replace($"{appName.Key} ", "").Replace(" [Approved]", "").Replace(".", "-").Replace("/n", "");
// Add the Name and version to the chocoApps dictionary from the chocoTempList
chocApps.Add(appName.Value, version);
}
#endregion
}
}
}
}
#endregion
#region CSV apps to Dictionary
private void CsvAppsToDic()
{
foreach (var app in csvData)
csvApps.Add(app.name, app.version);
}
#endregion
#region Compare Versions
private void CompareVersions()
{
// Run this for each entry in the chocApps Dictionary
foreach (var cApp in chocApps)
{
// If the
foreach (var app in csvApps)
{
// Find the matching name
if (app.Key == cApp.Key)
{
// Check if versions match
if (app.Value == cApp.Value)
{
// If the versions match
//Global.WriteVersion()
Console.WriteLine("Versions match :D");
Console.WriteLine($"{app.Value}a");
Console.WriteLine($"{cApp.Value}a");
}
else
{
// If they don't match
Console.WriteLine("This Version should have matched but it doesn't match :(\nRaw print outs:");
Console.WriteLine($"{cApp.Value}"); // chocoApps Dict
Console.WriteLine($"{app.Value}"); // csvApps Dict
// Heres where the funny bit happens :D
// Note how I have added some characters to the end of the line *abc
Console.WriteLine("\n\n");
Console.WriteLine($"{cApp.Value}*abc"); // chocoApps Dict
Console.WriteLine($"{app.Value}*abc"); // csvApps Dict
}
}
}
}
}
#endregion
}
}
This else statement should not have been called since the two strings should have matched.
Here's a screenshot which includes the console output of the running code.
it might just be case of white space, try:
if (app.Value.Trim() == cApp.Value.Trim())
{
//etc
}
edit: Trim() removes all white space at the start and end of the string including \r and \n also, so will also fix your issue above due to /n i.e. replace .Replace("/n","") with Trim() where you assign the string. Covers a number of issues with simpler code.

Ban a variable from a list with a "ban" list

How can I ban a variable from a list without removing it from that list by adding the variable to a list of "banned" variable?
I wish to be able to type in a string. That string is compared to the file names in a folder. If there is a match, the file is read. If I type this same string again, the file should not be read again. There for I want to have a list of "banned" string that is checked whilst typing to avoid the file to be read again.
I have tried a few ways but not getting there. Below is an example of my last attempt.
What would be the best way?
public class test
{
string scl= "test3";
List <string> lsf,lso;
void Start ()
{
lsf=//file names
new List<string>();
lso=//files open
new List<string>();
lsf.Add("test0");
lsf.Add("test1");
lsf.Add("test2");
lsf.Add("test3");
lsf.Add("test4");
lso.Add("idhtk49fngo");//random string
}
void Update ()
{
if
(
Input.GetKeyDown("a")
)
{
for
(
int i=0;
i<lsf.Count;
i++
)
{
if(lsf[i]==scl)
{
Debug.Log
(i+" is read");
for
(
int j=0;
j<lso.Count;
j++
)
{
//how can i avoid reading
//lsf[3] here the second time
//"a" is pressed (by having "test3"
//added to a "ban" list (lso) )
if(scl!=lso[j])
{
lso.Add(lsf[i]);
}
}
}
}
}
}
Michael’s answer is the way to go here but it can be improved using the more appropriate collection available to keep track of opened files; if you want uniqueness use a set, not a list:
HashSet<string> openedFiles = new HashSet<string>();
public static bool TryFirstRead(
string path,
out string result)
{
if (openedFiles.Add(path))
{
result = File.ReadAllText(path);
return true;
}
result = null;
return false;
}
Also, I’d avoid throwing vexing exceptions. Give the consumer a friendly way to know if the file was read or not, don’t make them end up having to use exceptions as a flow control mechanism.
I didn't understand although if you want to replace a value from another list.
You can use the list index to create a new list with the values which you removed.
String list1 = {"hi", "hello", "World"};
String list2 = {"bye", "goodbye", "World"};
List1[1] = list2[1];
I would suggest such way:
public static List<string> openedFiles = new List<string>();
public static string ReadFileAndAddToOpenedList(string path)
{
if (openedFiles.Contains(path))
throw new Exception("File already opened");
// Instead of throwing exception you could for example just log this or do something else, like:
// Consolle.WriteLine("File already opened");
else
{
openedFiles.Add(path);
return File.ReadAllText(path);
}
}
The idea is - on every file read, add file to list, so you can check every time you try read file, if it was already read (or opened). If it is, throw exception (or do something else). Else read a file.
You could instead of making it a string list use your own class
public class MyFile
{
public string Name;
public bool isOpen;
public MyFile(string name)
{
Name = name;
isOpen = false;
}
}
List<MyFile> lsf = new List<MyFile>()
{
new MyFile("test0"),
new MyFile("test1"),
new MyFile("test2"),
new MyFile("test3"),
new MyFile("test4")
};
Than when you read the file set isOpen to true
MyFile[someIndex].isOpen = true;
and later you can check this
// E.g. skip in a loop
if(MyFile[someIndex]) continue;
You could than also use Linq in order to get a list of only unread files:
var unreadFiles = lsf.Select(f => f.Name).Where(file => !file.isOpen);

Parsing key value pairs c#

I've been having issues attempting to parse key value pairs from a text file. I've been scouring for libraries that can do what I'd like as I do not have the ability to create a class that can do this.
Here is the beginning of my file along with a portion of commented out text and key value pairs:
#!version:1.0.0.1
##File header "#!version:1.0.0.1" can not be edited or deleted, and must be placed in the first line.##
#######################################################################################
## Account1 Basic Settings ##
#######################################################################################
account.1.enable = 1
account.1.label = Front
account.1.display_name = Front
What I'm looking to do is grab these values, and be able to update them to within the file in the same location in the file that they are as these files need to remain human readable.
I've looked into Nini as this library seems to be able to do what I'd like, however the error I continue to have is based off of the line 1 of my file as it is not a key value pair.
Expected assignment operator (=) - Line: 1, Position: 19.
I read through the source of Nini, and it seems there is a way to condition the reader to use Mysqlstyle, which would use "#" as comments, but I'm unsure how to adjust it or if it is done automatically as it is completely over my head.
I understand that my files aren't legitimate ini files and there is probably a limitation within the Nini library as it searches for the section that the key value pairs are in.
The code I've attempted to use to parse and display this text to edit with Nini is as follows:
public void EditCFG(string file)
{
if (!string.IsNullOrWhiteSpace(file))
{
IniConfigSource inifile = new IniConfigSource(file);
account_1_display_name.Text = inifile.Configs[""].Get("account.1.display.name");
}
}
Could someone please point me in the right direction?
EDIT
Thanks to #rowland-shaw, I have found the solution:
private IConfigSource source = null;
public void EditCFG(string file)
{
if (!string.IsNullOrWhiteSpace(file))
{
IniDocument inifile = new IniDocument(file, IniFileType.MysqlStyle);
source = new IniConfigSource(inifile);
account_1_display_name.Text = source.Configs["account"].Get("account.1.display_name");
}
}
However, this wasn't completely the answer. I had to also implement sections within the file. After testing my equipment that grabs these files with the updated text, everything was a success.
You need to specify the IniFileType, i.e.:
IniConfigSource inifile = new IniConfigSource(file, IniFileType.MysqlStyle);
Long example:
IniDocument inifile = new IniDocument(file, IniFileType.MysqlStyle);
IniConfigSource source = new IniConfigSource(inifile);
If that is how the format is going to be (key = value and # for comments) in the file, you could do the following (c# pseudocode-ish, you can do the trivial stuff yourself):
Dictionary<string, string> dictionary;
foreach(string line in file)
{
if(string.IsNullOrWhiteSpace(line)) continue;
// Remove extra spaces
line = line.Trim();
if(line[0] == '#') continue;
string[] kvp = line.Split('=');
dictionary[kvp[0].Trim()] = kvp[1].Trim(); // kvp[0] = key, kvp[1] = value
}
Then you can use the created dictionary like account_1_display_name.Text = dictionary["account.1.display.name"];
i can recommend my library Nager.ConfigParser you can easily obtain them over nuget.
Here the example for your configuration
var config = "#comment1\r\naccount.1.enable = 1\r\naccount.1.label = Front";
var configConvert = new ConfigConvert();
var item = configConvert.DeserializeObject<AccountCollection>(config);
public class AccountCollection
{
[ConfigKey("account.")]
[ConfigArray]
public Account[] Accounts { get; set; }
}
public class Account : ConfigArrayElement
{
public int Enable { get; set; }
public string Label { get; set; }
[ConfigKey("display_name")]
public string DisplayName { get; set; }
}

Phone version of Universal App seems to be caching database even after uninstall

I'm working on a Universal App using SQLite, and I've been using this tutorial along with SQLite for Windows Runtime (Windows Phone 8.1) and sqLite-net to get started.
I'm using this to check if the database exists:
bool exists = true;
try {
var file = await ApplicationData.Current.LocalFolder.GetFileAsync( "database.db" );
} catch {
exists = false;
}
and if not running some insert queries to populate default data:
if( !exists ) {
var conn = new SQLiteConnection( "database.db );
conn.CreateTable<MyClass>();
MyClass.Insert( "Default data value" );
}
where MyClass is
[Table( "MyClass" )]
public class MyClass {
public MyClass() {
this.ID = -1;
this.Name = string.Empty;
}
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
[NotNull]
public string Name { get; set; }
internal static void Insert( string Name ) {
var myclass = new MyClass();
myclass.Name = Name;
var conn = new SQLiteConnection( "database.db" );
try {
if( myclass.ID == -1 ) conn.Insert( myclass );
} catch { }
}
public async static Task<List<MyClass>> List() {
var conn = new SQLiteAsyncConnection( "database.db" );
var rs = conn.Table<MyClass>().OrderBy( t => t.ID );
return await rs.ToListAsync();
}
}
The problem is every time I do a fresh deploy (after uninstalling from my test device), and the code correctly determine the database doesn't exist and performs the inserts, I'm left with an increasing number of records. More specifically, I'm doing an insert of four default values, but at my last deploy that table currently has 124 records (meaning I've deployed 31 times) and looking at the data, it's the same four values repeated. Stepping through the code, only four inserts are occurring, as expected.
It seems like the database is being cached somewhere. I've run the Windows Phone Power Tools and verified there are no files after uninstall. Am I missing something here?
I had a similar problem some time ago (although not with SQLite). Try to check the "Disable automatic backup/restore" checkbox in WMAppManifest.xml (Packaging tab).
In general though, new SQLiteConnection( "database.db" ); by itself does not guarantee a new file being created and your code doesn't currently ensure the file does not already exist: you are catching all exceptions while your condition is only covered by FileNotFoundException - the GetFileAsync may fail for other reasons than the file not existing. I would suggest catching the FileNotFoundException exception to begin with, and possibly also creating the file explicitly in code.

Categories

Resources