Import Sharepoint Document Library using SSIS - sharepoint

We need to import SharePoint Document Library (which could be holding multiple document in multiple formats) to a destination folder (on different server) using SSIS.

There are open source SSIS adapters available for SharePoint. You can use these.
http://sqlsrvintegrationsrv.codeplex.com/
http://sqlsrvintegrationsrv.codeplex.com/releases/view/17652

You can also create a script task in ssis and use c# to extract files from SharePoint Library to a local folder. Make sure the SharePoint url only contains siteurl/Library/Folder/File (no special characters). Below copies one file but can be modified to copy multiple files. Good luck.
using System.net;
public void main ()
{
WebClient Client = new WebClient();
Client.UseDefaultCredentials = true;
Client.DownloadFile("yourSharePointurl/File.ext",
#"YourLocalFolder/File.ext");
Dts.TaskResult = (int)ScriptResults.Success;
}

Change this "using System.net;" to using "System.Net;"
My compilation error got fixed

Related

Azure Logic App, Cant get data from CreateFile Function

So I've noticed a strange behavior which I would like to share and see if anyone has had the similar problem.
We are using on Prem solution where we pickup a file or a http event request, map it to an outgoing xml xsd/schema and then create the file later on prem.
The problem was that the system where we save the file does not cooperate so good with the logic app, the logic app failes sometime because the system takes the file before the logic app can finish writing the full content.
The system receiving the files only read .xml files, so we though we should first rename the files to tmp, let logic app create the files and then rename them.
This solution sounded quite simple before we started actually applying it to the logic app.
If we take FileSystem function which has Rename File function and use the parameters “Name” from the create file on prem
{
"statusCode": 404,
"message": "Resource not found"
}
We get the message 404 that the resource is not found, now this complicates a lot of things, I’ve checked the privileges on the account that should not be an issue.
What we also have tried is listing all files in the folder, creating a foreach and then adding a rule and the Rename File function. This makes it work but the logic app does not cope well with receiving a lof of files at ones with that solution.
But the Rename Files works when it’s in a foreach loop and we extract the file names in a list from root folder or normal folder.
But why does it not work with just using the Rename Function? Is this perhaps an azure function bug in the Logic app Rename File Function?
So after discussing with Microsoft support on Azure they have actually confirmed that there is a bug with the “Create File” function.
It looks like all the data and information is actually lost during that functions, the support technicians do not know why that is happening but they have had similar cases which people have reported.
I have not stumbled across any of those posts, but I will post how we solved the problem with a work around.
FYI, The support team has taken the case further so that the developers at azure should look into it, because it’s not just “name” tag which is lost from Create a File, ( it’s all valuable options are actually lost ).
So first we initialize a variable and then actually set the variable name with two steps before we create the file:
The name is set with a temp name and a GUID.
Next step is creating the file with the temp-name used in function “Set Variable Temp FileName”
And on the Rename File function we use the Path from where we store the temp file and add \”FILENAME”
And add the “New Name” which we want to use.
This proved to work but is a workaround, support confirmed that you should be able to just use the “RenameFile” after creating the file with a temp name and changing it to the desired name.
But since Create a File does not send or pass any information at all from this list we have to initialize Variables to make it work.
If anyone has stumbled on the same problem where the Backend system reads the files before they are managed to be created by the logic app and you need some workaround this worked good for me.
Hope it helps!
We recently had the same issue; and the workaround of renaming the file also failed.
The cause seems to be that the Azure On Prem Gateway creates a file (or renames a file), then releases its lock, before checking that the file exists. In the gap between releasing the lock and checking that the file exists, the file may be picked up (deleted) thus causing LogicApps to think the step failed (reporting a 404 error), and thus confusion.
Our workaround was to create a Windows service which we hosted on the file servers (so they'd be able to respond to file changes before anything else on the network). This service has a configuration file which accepts a list of paths and file filters, and it uses the FileSystemWatcher to monitor for new files, or renamed files. When it detects a match it takes out a read lock on the file. This ensure it's not blocked by anything writing to the file (i.e. so it doesn't have to wait for the On Prem Gateway's write aciton to complete before obtaining its own lock), but whilst our service holds its lock the file can't be deleted (so the consumer can't remove the file / buying time for the On Prem Gateway to perform it's post-write read and report success). Our service releases its own lock after a defined period (we've gone with 30 seconds, though you could likely get away with much less). At that point, the consumer can successfully consume the file.
Basic code for the file watch & locking logic below:
sing System;
using System.IO;
using System.Diagnostics;
using System.Threading.Tasks;
namespace AzureFileGatewayHelper
{
public class Interceptor: IDisposable
{
object lockable = new object();
bool disposed = false;
readonly FileSystemWatcher watcher;
readonly int lockTimeInMS;
public Interceptor(string path, string filter, int lockTimeInSeconds)
{
lockTimeInMS = lockTimeInSeconds * 1000;
watcher = new FileSystemWatcher();
watcher.Path = path;
watcher.Filter = filter;
watcher.NotifyFilter = NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.FileName
| NotifyFilters.DirectoryName;
watcher.Created += OnIncercept;
watcher.Renamed += OnIncercept;
}
public Interceptor(InterceptorConfigElement config) : this(config.Path, config.Filter, config.TimeToLockInSeconds) { Debug.WriteLine($"Loaded config ${config.Key}: Path: '${config.Path}'; Filter: '${config.Filter}'; LockTime: : '${config.TimeToLockInSeconds}'."); }
public void Start()
{
watcher.EnableRaisingEvents = true;
}
public void Stop()
{
if (watcher != null)
watcher.EnableRaisingEvents = false;
}
private async void OnIncercept(object source, FileSystemEventArgs e)
{
using (var fs = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
Debug.WriteLine($"Locked: {e.FullPath} {e.ChangeType}");
await Task.Delay(lockTimeInMS);
}
Debug.WriteLine($"Unlocked {e.FullPath} {e.ChangeType}");
}
public void Dispose()
{
if (disposed) return;
lock (lockable)
{
if (disposed) return;
Stop();
watcher?.Dispose();
disposed = true;
}
}
}
}

kofax export script project setup

For my first export script I took the KCEC example and the APIRefExport.chm documentation to create my project by replacing the example code with my own.
I would like to create a clean export script from scratch.
I created a new class library project and called it EmptyExportScript (placeholder). The target framework is .Net 4. The platform target is x86 and the output path is .....\Program Files (x86)\Kofax\CaptureSS\ServLib\Bin\. When debugging I would like to start the administration module so I set this path .......\Program Files (x86)\Kofax\CaptureSS\ServLib\Bin\.
The option "Make assembly COM-Visible" is checked and I added the Kofax.ReleaseLib.Interop.dll to the references.
For the KfxReleaseScript.cs I added this code
[ClassInterface(ClassInterfaceType.None)]
[ProgId("KFXTS.EmptyExportScript.KfxReleaseScript")]
public class KfxReleaseScript
{
public ReleaseData documentData;
// public KfxReturnValue OpenScript()
// public KfxReturnValue ReleaseDoc()
// public KfxReturnValue CloseScript()
}
For the KfxReleaseScriptSetup.cs I added this code
[ClassInterface(ClassInterfaceType.None)]
[ProgId("KFXTS.EmptyExportScript.KfxReleaseScriptSetup")]
public class KfxReleaseScriptSetup
{
public ReleaseSetupData setupData;
// public KfxReturnValue OpenScript()
// public KfxReturnValue CloseScript()
// public KfxReturnValue RunUI()
// public KfxReturnValue ActionEvent(KfxActionValue actionID, string data1, string data2)
}
Lastly I added a Form to the project when running the UI.
For registration I added a EmptyExportScript.inf with this content
[Scripts]
Empty Export
[Empty Export]
SetupModule=EmptyExportScript.dll
SetupProgID=KFXTS.EmptyExportScript.KfxReleaseScriptSetup
SetupVersion=10.2
ReleaseModule=EmptyExportScript.dll
ReleaseProgID=KFXTS.EmptyExportScript.KfxReleaseScript
ReleaseVersion=10.2
SupportsNonImageFiles=True
SupportsKofaxPDF=True
RemainLoaded=True
SupportsOriginalFileName=False
When building the project .dll and .inf file get placed into the kofax bin directory.
I recognized that other scripts have a .pdb and .dll.config file in there too.
How do I get them?
When trying to install the custom script, I can add it to the script installation manager but I can't install it. There is nothing to install so I think I'm missing the .pdb and .dll.config file.
Is anything else missing?
Thanks for help :)
Kofax does not need a pdb file, but they are handy if you want to debug your connector and attach it to the release.exe process (learn more about them here).
I would not recommend changing the output path itself to Capture\Bin, but rather create a post-build event:
For example, the following line copies all required files to a separate folder under the CaptureSS\Bin folder:
xcopy "$(TargetDir)*" "C:\Program Files (x86)\Kofax\CaptureSS\ServLib\Bin\SmartCAP\kec\SmartCAP.KEC.Template\" /Y /S
Having a dll.config file is possible, but rare. I would rather recommend storing process-specific data in a custom storage string object of the respective batch class definition (which has the added benefit that you can just import/export the definition along with the batch class, and that you can display and have it changed it in setup form). Having said all that, back to your initial issue - the connector can't be installed.
COM visibility
The assembly needs to be COM-visible, but you mentioned that it was. For the sake of completeness, here's what you will need to do. Note that the GUID must be unique (only relevant if you copied an existing solution):
If you're installing the connector on a different machine, you will need to register it first using regasm.exe - here's an example:
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe" SampleExport.dll /codebase /tlb:SampleExport.tlb
ProgIds
Then, your .inf file needs to contain the precise ProgIDs:
[Scripts]
SampleExport
[SampleExport]
SetupModule=SampleExport.dll
SetupProgID=SampleExport.Setup
SetupVersion=11.0
ReleaseModule=SampleExport.dll
ReleaseProgID=SampleExport
ReleaseVersion=11.0
SupportsNonImageFiles=True
SupportsKofaxPDF=True
Both your ReleaseScript.cs and ReleaseSetupScript.cs files need the correct attribute, for example:
[ProgId("SampleExport")]
public class ReleaseScript
If that all still does not work, please provide us with the detailed error message (to be found at CaptureSV\Logs).
I had to change the file format from UTF-8 to UTF-8 without BOM.
This worked for me.

What is the proper way to use Interop in a regular, non Office, application?

The following has been my development strategy for a long time. I divide the Excel applications in two large classes:
(a) Excel does not have to be present: The app may even run in an OS such as Linux, etc. I use 3rd. party Excel libraries. In Windows, I take advantage of resources such as OpenXML or even better: ClosedXML.
(b) Office Applications such as AddIns: Interop.
However, for a rather complex worksheet that is handled by multiple applications, I have decided that it is best to allow Excel itself to do all the work. I have the typical AddIns but am in the process of porting a regular app which used ClosedXML to Interop. As you may see in the following post, some colleagues have had trouble going that route. The missing class Globals seems to present a serious obstacle.
https://social.msdn.microsoft.com/Forums/en-US/cf4b0ca8-9c3b-41df-a24a-b2c195eaee4e/cannot-access-globals-object-from-c-console-application?forum=exceldev
What is the proper way to use Interop in a regular (non AddIn, non Office) application?
TIA
Here's the answer:
using Microsoft.Office.Interop.Excel;
public class InteropExcel
{
private Application excelApp;
private Workbook workbook;
private Worksheet worksheet;
internal void createExcelFile(string targetFilepath)
{
excelApp = new Application();
excelApp.Visible = false;
workbook = excelApp.Workbooks.Add();
worksheet = excelApp.ActiveSheet;
workbook.SaveAs(targetFilepath);
excelApp.Quit();
}
}

Create docx file from a template file in java

I need to create docx files based on a templates.
The template should contain the place holders and I should be able to fill the the place holders from java .
Is it possible to do it , If so suggest me the good and efficient way to do it .
A little late for the original question, but if anyone else needs to dynamically create docx documents from templates, you might want to have a look at the DocxStamper Java library which I created on top of docx4j.
It allows to use the Spring Expression Language in docx templates and you can create a document out of a template with a couple lines like this:
MyData data = ...; // your own POJO containing the data
InputStream template = ...; // InputStream to the template file
OutputStream out = ...; // OutputStream to the resulting document
DocxStamper stamper = new DocxStamperConfiguration()
.build();
stamper.stamp(template, context, out);
out.close();
As discussed elsewhere before, there are 3 basic approaches:
BEST: content control data binding
cheap/cheerful: Variable replacement (ie magic strings on the document surface), but brittle (the split run problem)
LEGACY: MERGEFIELD with or without other field codes.
Docx4j supports all three approaches, but we generally recommend content control databinding, since it aligns with Microsoft's direction (as best can be ascertained), and is most powerful.
You'll want to consider the technical skills of your template authors.
See https://github.com/centic9/poi-mail-merge for a simple "Variable replacement" method. It does not work if one replacement-string has multiple formats applied, but does work well for simple cases where the template is carefully crafted.
Basically it reads the template and data from CSV or an Excel file and then merges it into multiple result files, one for each line of data.
It works on the DOCX XML content, so is not fully using Apache POI XWPF support, but this way formatting and other things from the template are used as expected without the need for full support for everything in Apache POI (which has DOCX support still as part of the "scratchpad" component as support is not considered fully done yet).
You can use Word template with following syntax of LINQ Reporting to achieve your requirements using Aspose.Words for Java.
<< tag_name [expression] -switch1 -switch2 ...>>
A tag body typically consists of the following elements:
A tag name
An expression surrounded by brackets
A set of switches available for the tag, each of which is preceded by the “-“ character
Assume, that you have the Sender class defined in your application as follows:
public class Sender {
public Sender(String name, String message) {
_name = name;
_message = message;
}
public String getName() {
return _name;
}
public String getMessage() {
return _message;
}
private String _name;
private String _message;
}
To produce a report containing a message of a concrete sender on its behalf, you can use a template document with the following content.
<<[s.getName()]>> says: "<<[s.getMessage()]>>."
To build a report from the template, you can use the following source code.
Document doc = new Document(getMyDir() + "temp_HelloWorld.docx");
Sender sender = new Sender("LINQ Reporting Engine", "Hello World");
ReportingEngine engine = new ReportingEngine();
engine.buildReport(doc, sender, "s");
doc.save(getMyDir() + "out.docx");
I work with Aspose as Developer evangelist.

Can MEF Support Multiple Plug-ins Using Different Interfaces?

I have a need to load one DLL (Data) using one interface (IDataSender) and another DLL (Message) using another interface (IMessageSender). The code below is generating an error that the DLL being loaded doesn’t support the interface from the other DLL. Looks like each DLL much support all interfaces used by MEF.
Any idea how to load DLLs using different interfaces? I tried using [ImportMany] but that seems to load multiple DLLs using the same interface. Can MEF support multiple Interfaces?
[Import(typeof(IDataSender))]
public IDataSender DataSender;
[Import(typeof(IMessageSender))]
public IMessageSender MessageSender;
catalog_data = new AssemblyCatalog(#".\ABC.Data.dll");
container_data = new CompositionContainer(catalog_data);
container_data.ComposeParts(this);
catalog_message = new AssemblyCatalog(#".\ABC.Message.dll");
container_message = new CompositionContainer(catalog_message);
container_message.ComposeParts(this);
// DLL 1
namespace ABC.Data
{
[Export(typeof(IDataSender))]
public class DataClass : IDataSender
{
}
}
// DLL 2
namespace ABC.Message
{
[Export(typeof(IMessageSender))]
public class MessageClass : IMessageSender
{
}
}
Thank you for any help offered. I am new to MEF and can't figure out how to get that working.
Kamen
You don't need two containers to do this. One is enough. To do so, you need to use an AggregateCatalog that holds both AssemblyCatalogs.
catalog_data = new AssemblyCatalog(#".\ABC.Data.dll");
catalog_message = new AssemblyCatalog(#".\ABC.Message.dll");
container = new CompositionContainer(new AggregateCatalog(catalog_data, catalog_message);
container.ComposeParts(this);
The problem with your code was that none of the two containers, contained both parts needed to satisfy the imports. Each one contained one of the necessary parts. With the AggregateCatalog you can add multiple catalogs to a container, which is what you actually need. In almost any case, a single container is enough.

Resources