Delete files based on variable SSIS Script - c#

I have a script in ssis which deletes the file and I need to modify the script by adding variable so that process can be executed dynamically. I would appreciate if some can help me out by showing how to add variable in the script below:-
enter public void Main()
{
int RetentionPeriod = 0;
string directoryPath = #"\\ABCD\EFG\HIJ";--need to add location variable
string[] oldFiles = System.IO.Directory.GetFiles(directoryPath, "*.csv");
foreach (string currFile in oldFiles)
{
FileInfo currFileInfo = new FileInfo(currFile);
if (currFileInfo.LastWriteTime < (DateTime.Now.AddDays(-RetentionPeriod)))---need to add date variable here
{
currFileInfo.Delete();
}
}
// TODO: Add your code here
Dts.TaskResult = (int)ScriptResults.Success;
}
}
}
As shown in the script I need to add two variable namely location variable and Date variable.Both the variables have string data type
I know this question is very silly but I have no exp in writing SSIS scripts

string directoryPath = Dts.Variables["User::NameOfStringVariable"].Value
You also have to add the variable to the ReadOnly list on the script task configuration. here is a screen shot from another question that shows you where to make the variable accessible to the script:
and in case you don't know where/how to add a variable to a package. One easy way is to right click on the grey area of the control flow and choose variables and that will bring up the variables window then simply add the variable with the appropriate datatype that you want.

this is over coded: try this:
set a variable as answered above to contain the file path
Add this to main after setting a System.IO; reference
public void Main()
{
string FilePath = Dts.Variables["UserControl::File"].Value.ToString();
if (File.Exists(FilePath))
{
File.Delete(FilePath);
}
Dts.TaskResult = (int)ScriptResults.Success;
}

Related

How to replicate a global variable in C#?

I have a variable in one loop in C# that cannot be recognized in the other one, and I am aware that it is not possible to create a true global variable in C#, however I wonder if one can mimic one. Some of my code is this:
foreach (string line in lines)
{
if (line.Contains("write"))
{
var tempctr = line.Replace("(", "");
var tempctr2 = line.Replace(")", "");
var ctr = tempctr2.Remove(0, 6);
Console.Write(ctr);
}
else if (line.Contains("sayinput"))
{
Console.Write(usrinput);
}
else if (line.Contains("inputget"))
{
var tempctr = line.Replace("(", "");
var tempctr2 = line.Replace(")", "");
var ctr = tempctr2.Remove(0, 9);
Console.Write(ctr);
string usrinput = Console.ReadLine();
}
}
The code reads from a text file and runs a certain command based on what is in the text. My intention is for it to create a variable with inputget and spit it back out with sayinput.
And the first usrinput reference is an error, since the variable is declared outside of the loop.
You don't need a global variable here. Just declare usrinput outside your loop, like so:
string usrinput = "";
foreach (string line in lines)
{
if (line.Contains("write"))
{
//...
}
else if (line.Contains("sayinput"))
{
Console.Write(usrinput);
}
else if (line.Contains("inputget"))
{
// ...
usrinput = Console.ReadLine();
}
}
it is not possible to create a true global variable in C#,
Static variable on a class. Done. Global in the definition of any global variable (i.e. you must be in the same process). And standard C#.

Unity3D Android: How to load images and sounds dynamically (from file) from folder after the build?

Edit:
As it was marked as a duplicate of Using Resources Folder in Unity
I need to say that it IS different. Since I KNOW how to use the Resource Folder and if you would have read the whole text, you would have seen that I'm already using it like it is said in the post. I' getting trouble with doing it when the build is already done, since the .apk file doesn't let me access the folder afterwards, if I did not instantiate all images beforehand. So PLEASE read it again and don't mark it as a duplicate especially when the problem is stated as a different one already in the titel... Thanks!
Original:
I'm new to Stack Overflow so I hope, I give you all informations you need.
I'm developing a Serious Game in Unity3D, where I need to instantiate a various number of prefab-tiles and change the sprites and sounds of it dynamically when the scene is changed. I'll explain more after the code.
Here the code, which works perfectly in the Editor:
using UnityEngine;
using UnityEngine.SceneManagement;
#if UNITY_EDITOR
using UnityEditor;
#endif
using System;
using System.IO;
public class SourceManager : MonoBehaviour
{
private string path;
private string filePath;
private string wrongSoundDir;
private string rightSoundDir;
private string letter;
private string levelsFile = "LevelsToLoad.csv";
private string[] listOfCounterletters;
private string[] wordsOne;
private string[] wordsTwo;
private string letterOne;
private string letterTwo;
private string text;
private string text2;
private void Awake()
{
Debug.Log("SourceManager active.");
path = GetPath();
if (SceneManager.GetActiveScene().buildIndex != 0)
{
filePath = GetFilePath(path);
GetLettersFromFile(out letterOne, out letterTwo);
letter = letterOne;
if (SceneManager.GetActiveScene().name == "Words" || SceneManager.GetActiveScene().name == "Container")
{
GetWordsFromFile(letter, out wordsOne);
GetWordsFromFile(letterTwo, out wordsTwo);
}
SetRightWrongSounds();
}
}
private string GetPath()
{
// Returns the path of the active scene
Debug.Log("Getting path...");
return SceneManager.GetActiveScene().path.Remove(SceneManager.GetActiveScene().path.LastIndexOf('/') + 1);
}
private string GetFilePath(string path)
{
// Returns the filepath of the active scene (removes "Assets/Resources/" part)
Debug.Log("Getting filePath...");
return path.Replace("Assets/Resources/", "");
}
public void SetRightWrongSounds()
{
// sets right and wrong sounds
wrongSoundDir = "mainMusic/general/wrong";
rightSoundDir = "mainMusic/general/right";
}
private void GetLettersFromFile(out string posL, out string negL)
{
if (path != null)
{
text = File.ReadAllText(path + "letters.txt");
listOfCounterletters = text.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
posL = listOfCounterletters[0];
negL = listOfCounterletters[1];
}
else
{
Debug.LogError("Path not set (yet). Cannot set pos and neg letters.");
posL = null;
negL = null;
}
}
private void GetWordsFromFile(string letter, out string[] words)
{
if (letter != null)
{
text = File.ReadAllText(path + letter + ".csv");
words = text.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
}
else
{
Debug.LogError("Letter not set (yet). Cannot set words list.");
words = null;
}
}
public void ChangeToScene(int number)
{
if (number < SceneManager.sceneCountInBuildSettings)
{
if (SceneManager.GetActiveScene() != SceneManager.GetSceneByBuildIndex(number))
SceneManager.LoadScene(number);
else
Debug.LogError("Scene already active.");
}
else
{
Debug.LogError("Scenenumber is not within the Build Settings.");
}
}
public string GetLetterOne() { return letterOne; }
public string GetLetterTwo() { return letterTwo; }
public string[] GetWordsOne() { return wordsOne; }
public string[] GetWordsTwo() { return wordsTwo; }
public string GetDirectory() { return path; }
public string GetFileDirectory() { return filePath; }
public string GetWrongSoundDir() { return wrongSoundDir; }
public string GetRightSoundDir() { return rightSoundDir; }
}
So in the Unity Editor I simply do it by getting the path, where my scene is located (I need it to be like this and not in a separate scenes-folder, because I need several scenes with the same name but different content and the whole scene must be edited from people, who don't know how to use unity, so I want them to simply copy-paste a folder and replace the content, so they don't have to mess around with the code or even opening unity).
Afterwards I use the function GetLettersFromFile to get several letters (which will be changed the whole time, which is why I need it to be dynamic).
Then I have many scenes with different names and in the ones with the name "Words" or "Container" I have two .csv-files in the folder, where they are in, with all the names of sprites/sounds(same name), which need to be instantiated.
E.g. I could insert 100 images and 100 sounds, but only write 10 of them in this list (csv), so only 10 of them need to be instantiated as a prefab-tile.
Here a sample of the code I use to intsantiate the tiles:
files_dir = sourceManager.GetComponent<SourceManager>().GetFileDirectory();
GameObject[] InitTiles(string myletter, string[] text)
{
GameObject[] newObj = new GameObject[text.Length - 1];
for (int i = 0; i < text.Length - 1; i++)
{
Debug.Log(files_dir + text[i]);
zVal = -20.0f + ((i + 2) / 20);
clone = (GameObject)Instantiate(tile, new Vector3(UnityEngine.Random.Range(-180, 180), UnityEngine.Random.Range(-50, 50), zVal), Quaternion.identity);
clone.gameObject.GetComponent<SpriteRenderer>().sprite = Resources.Load<Sprite>(files_dir + text[i]);
clone.gameObject.GetComponent<AudioSource>().clip = Resources.Load<AudioClip>(files_dir + text[i]);
clone.gameObject.GetComponent<Dragable>().dragable = true;
clone.gameObject.GetComponent<Dragable>().letter = myletter;
newObj[i] = clone;
}
return newObj;
}
As you can see I want them to be dragable and if I start to drag them, they shall play the sound they got once.
So all in all:
I read a csv-file and save the content as a string[]
I go through the string[] and instantiate a tile-prefab and set its sprite to an image from the folder with e.g. the name "mother.png" and its audioclip to a clip with the name "mother.wav"
And now I need to do the same for Android, but I just cannot figure out how. I read what felt like a million posts and tried www and streamingassests but it doesn't work so I thought maybe I'm just doing it wrong and I wanted to ask you guys and girls for help.
I didn't want to post the wrong code, because it all just gets confusing.
I hope you have enough information. Please feel free to ask, if something's not clear yet.
Thank you very much!
Best,
Nina
Screeshot of the location of all images for one example-level:
location of sprites/sounds for the level words_easy_MN
all files within the mentioned directory
Example how it should look like later on Android
See example: in the middle there are two tiles. After reading the content from letters.txt and M.csv the algorithm sets the sound of the right tile to "M" and of the left one to "blume" (one example from the list). The right tile also gets the image of the "blume" (=a flower).
I already have everything in the folder. I need the tile to instantiate automatically from the list..
You need to re-write your code. Almost all of them. Unfortunately, I can't do that for you in this answer but will explain what's wrong and how to fix them.
The Resources folder is special and cannot be accessed with the File.XXX functions. The Resources.Load function is a special API dedicated for this. It's the only way to read from the Resources folder.
As shown in your screenshot, the file you want to read is from the "Resources/levels/words_diff_MN/" folder folder.
Let's say you want to load the "letters.txt" file from the "Resources/levels/words_diff_MN/" path, remove "Resources" from the path. Also remove the file extension. The final path to read from is levels/words_diff_MN/letters"
Resources.Load and TextAsset are used to load text files:
To load the "letters.txt" file from the "Resources/levels/words_diff_MN/" path:
TextAsset txtAsset = (TextAsset)Resources.Load("levels/words_diff_MN/letters")", typeof(TextAsset));
string textFile = txtAsset.text;
To load the M.mp3/ogg sound file:
AudioClip audio = Resources.Load("levels/words_diff_MN/M", typeof(AudioClip)) as AudioClip;
To load the blume image file:
Sprite sprite = Resources.Load("levels/words_diff_MN/blume", typeof(Sprite)) as Sprite;
If the blume image is marked as multi sprite then load it as an array:
Sprite[] sprite = Resources.LoadAll<Sprite>("levels/words_diff_MN/blume") as Sprite[];
You can find complete list of examples for other file types here.

Why does the SSIS Script Task fail to evaluate an expression?

SSIS Script Task Error
I have a table with directories and file names then which i want to use as a connection string to/from a text file.
I use a foreach loop to get the values from the table assigned to variables, than i have an expression variable which is a combination from the source Dir + source filename, and since there is no other way to check if a file exists in SSIS only with a script task, i did so
public void chkIfExist()
{
if (File.Exists(Dts.Variables["User::srcFull"].Value.ToString()))
{
Dts.TaskResult = (int)ScriptResults.Success;
}
else
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
}
note: User::srcFull is an expression veriable #[User::srcPath] + #[User::srcFile]
it kept on crashing on me, so i placed a watch in the script at runtime for Dts.Variables["User::srcFull"].Value.ToString() and i get and function evaluation timed out.
I tried to figure out whats going on and i came on the conclution that since the values are coming from a rawset that's why the script component cannot evaluate it...
Why does the expression fail to evaluate correctly within the Script Task? Does anyone how to resolve this issue?
Possible option:
You could use Execute SQL Task to fetch the record set instead of using a Data Flow Task.
SSIS 2012 package illustrating the example:
Let us assume that you have a table named dbo.FileNames in your data database with the some sample rows.
Create and populate table script:
CREATE TABLE dbo.FileNames(
srcPath nvarchar(255) NULL,
srcName nvarchar(60) NULL
);
GO
INSERT INTO dbo.FileNames (srcPath, srcName) VALUES
('C:\temp', 'File_1.txt')
, ('C:\temp', 'File_2.txt')
, ('C:\temp', 'File_3.txt')
;
GO
Configure the Control Flow tab as shown below. Place an Execute SQL Task to read the table data and store it in an object data type. Place a Foreach Loop Container after the Execute SQL Task and a Script Task within the Foreach Loop Container
Create the following variables. It is advisable to use the expression #[User::srcPath] + "\\" + #[User::srcFile] on the variable srcFull so that if the path is missing a trailing backslash, it will be added accordingly in between the path and file name.
Variable name Scope Data type Expression
-------------- ------------- ---------- -----------
FileNames SO_15072939 Object
srcFile SO_15072939 String
srcFull SO_15072939 String #[User::srcPath] + "\\" + #[User::srcFile]
srcPath SO_15072939 String
Configure the Execute SQL Task to run the below query against the connection manager to read the file path and name information.
SELECT srcPath, srcName FROM dbo.FileNames
The result set returned by the query should be stored into the variable FileNames of data type Object.
Configure the Foreach Loop Container to read the variable FileNames using Foreach ADO Enumerator.
Configure the two package variables to store the column values as the result set is being looped through.
Configure the Script Task Editor to read the variable srcFull
Add the below code to the Script Task.
Script task code in C# for SSIS 2008 and above:
#region Namespaces
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
using System.IO;
#endregion
namespace ST_f1d7b6ab42e24ad5b5531684ecdcae87
{
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
public void Main()
{
string filePath = Dts.Variables["User::srcFull"].Value.ToString();
MessageBox.Show(filePath);
Dts.TaskResult = File.Exists(filePath)
? (int)ScriptResults.Success
: (int)ScriptResults.Failure;
}
#region ScriptResults declaration
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
#endregion
}
}
Executing the package will display the variable value in MessageBox.
The package will fail in this sample because the path C:\temp\File_1.txt does not exist.
Response to OP's comment:
I did what you're showing me here, seems that my problem is that since the User::srcFile variable is added as a ReadWriteVariables to the script task (since i need to do some stuff with it in the same script) it's kinda locked so the User::srcFull variable who's definition is #[User::srcPath] + #[User::srcFile] cannot be evaluated..
I modified the variable srcFull from ReadOnlyVariables to ReadWriteVariables on Script Task Editor and the expression still evaluated correctly. I created those three files in the sample input and the package displayed each path correctly in the message box and completed the execution successfully.
Adding the variables srcPath and srcFile to the ReadWriteVariables section of Script Task Editor will only result in a conflict because now both Script Task and Foreach Loop Container are trying to update the same variables.
For starters, I would raise information events with all three variables prior to the call to File.Exists:
public void chkIfExist()
{
bool fireAgain = true;
Dts.Events.FireInformation(0,
"MyScriptTask",
String.Format("srcPath is \"{0}\"", Dts.Variables["User::srcPath"].Value),
"",
0,
ref fireAgain);
Dts.Events.FireInformation(0,
"MyScriptTask",
String.Format("srcFile is \"{0}\"", Dts.Variables["User::srcFile"].Value),
"",
0,
ref fireAgain);
Dts.Events.FireInformation(0,
"MyScriptTask",
String.Format("srcFull is \"{0}\"", Dts.Variables["User::srcFull"].Value),
"",
0,
ref fireAgain);
string fullPath = Dts.Variables["User::srcFull"].Value.ToString();
if (System.IO.File.Exists(fullPath))
{
Dts.TaskResult = (int)ScriptResults.Success;
}
else
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
}
The purpose here is to get a better view of what the failing record looks like.
You need to pass all the variables in the ReadOnlyVariables section in order for the scriptTask to evaluate them. In your case, I think your ReadOnlyVariables should be srcPath, srcFile, srcFull

Saving a string to a .setting variable

I'm trying to save a string variable from my FolderBrowserDialog.SelectedPath().
Using a breakpoint I can see that the string is correctly loaded onto SelectedPath(), but I can't save that string to the .settings file for the life of me. Any help?
public void LocateWoWFolder()
{
using (FolderBrowserDialog FileDialogWindow = new FolderBrowserDialog())
{
if (FileDialogWindow.ShowDialog() == DialogResult.OK)
{
//Using a breakpoint here I can see that nothing is loaded to .WoWFolderLocation.
Properties.Settings.Default.WoWFolderLocation = FileDialogWindow.SelectedPath.ToString();
}
}
}
The setting WoWFolderLocation is string type, and is a User scope setting. What am I doing wrong? :P
You need to call Properties.Settings.Default.Save().
:)
You must call ...
Properties.Settings.Default.Save();
Check out Using Settings in C#.

c# identifier expected?

I am trying to create a program to copy all the files from one directory to another. But I am running in a basic issue. It says indentifier expected when I try to compile on line 52.
public bool RecursiveCopy()
{
string origDir = #"D:\Documents and Settings\Dub\My Documents\HoN Updates\test";
string destDir = #"C:\Games\HoN";
bool status = false;
//get all the info about the original directory
var dirInfo = new DirectoryInfo(origDir);
//retrieve all the _fileNames in the original directory
var files = dirInfo.GetFiles(origDir);
//always use a try...catch to deal
//with any exceptions that may occur
try
{
//loop through all the file names and copy them
foreach (string file in Directory.GetFiles(origDir))
{
var origFile = new FileInfo(file);
var destFile = new FileInfo(file.Replace(origDir, destDir));
//copy the file, use the OverWrite overload to overwrite
//destination file if it exists
System.IO.File.Copy(origFile.FullName, destFile.FullName, true);
//TODO: If you dont want to remove the original
//_fileNames comment this line out
File.Delete(origFile.FullName);
status = true;
}
Console.WriteLine("All files in " + origDir + " copied successfully!");
}
catch (Exception ex)
{
status = false;
//handle any errors that may have occurred
Console.WriteLine(ex.Message);
}
return status;
}
public string origDir = #"D:\Documents and Settings\Dub\My Documents\HoN Updates\test"; // ERROR HERE
public string destDir = #"C:\Games\HoN"; // ERROR HERE
private static void RecursiveCopy(origDir, destDir)
{
Console.WriteLine("done");
Console.ReadLine();
}
You did not give type identifiers to your argument list here
static void RecursiveCopy(origDir, destDir)
should be
static void RecursiveCopy(string origDir, string destDir)
Your method RecursiveCopy has two parameters listed without their types. It should be this:
static void RecursiveCopy(string origDir, string destDir)
Here is your problem:
static void RecursiveCopy(origDir, destDir)
You don't specify the types for the parameters, perhaps you intended the following:
static void RecursiveCopy(string origDir, string destDir)
There are more issues however that I've noticed. It's possible you're still working on these, but from what you've posted:
You never call your RecursiveCopy method. Perhaps you meant to call it from Main() instead of declaring an overload with two parameters?
You declare two public fields origDir and destDir but then never use them. Instead you create two local variables in RecursiveCopy() and use these instead. Did you intend to create parameters or use the public fields instead?
Your copy is not actually true to its name of "recursive".
cYou are missing the parameter types in the RecursiveCopy method declaration. Just Change
static void RecursiveCopy(origDir, destDir)
to
static void RecursiveCopy(String origDir, String destDir)
and all is fine.

Categories

Resources